From 81e40e342dcf0cf68b609aacc99834f464a0b52b Mon Sep 17 00:00:00 2001 From: raoulvdberge Date: Thu, 8 Aug 2024 19:25:43 +0200 Subject: [PATCH 1/2] feat: pattern grid recipe transfer Also adds support for ghost dragging the new filter slots. --- CHANGELOG.md | 5 + README.md | 2 +- gradle.properties | 2 +- .../fabric/CraftingGridTransferHandler.java | 5 +- .../fabric/FilterDraggableStackVisitor.java | 98 +++++++++++++++ .../rei/fabric/GridFocusedStackProvider.java | 2 +- .../fabric/PatternGridTransferHandler.java | 113 ++++++++++++++++++ .../rei/fabric/ReiClientPlugin.java | 5 +- .../ReiRecipeModIngredientConverter.java | 18 +++ .../fabric/ResourceDraggableStackVisitor.java | 100 ++++++++++++++++ .../forge/CraftingGridTransferHandler.java | 5 +- .../forge/FilterDraggableStackVisitor.java | 98 +++++++++++++++ .../rei/forge/GridFocusedStackProvider.java | 2 +- .../rei/forge/PatternGridTransferHandler.java | 113 ++++++++++++++++++ .../rei/forge/ReiClientPlugin.java | 5 +- .../ReiRecipeModIngredientConverter.java | 18 +++ ...ava => ResourceDraggableStackVisitor.java} | 58 +++++---- 17 files changed, 617 insertions(+), 32 deletions(-) create mode 100644 refinedstorage-rei-integration-fabric/src/main/java/com/refinedmods/refinedstorage/rei/fabric/FilterDraggableStackVisitor.java create mode 100644 refinedstorage-rei-integration-fabric/src/main/java/com/refinedmods/refinedstorage/rei/fabric/PatternGridTransferHandler.java create mode 100644 refinedstorage-rei-integration-fabric/src/main/java/com/refinedmods/refinedstorage/rei/fabric/ResourceDraggableStackVisitor.java create mode 100644 refinedstorage-rei-integration-neoforge/src/main/java/com/refinedmods/refinedstorage/rei/forge/FilterDraggableStackVisitor.java create mode 100644 refinedstorage-rei-integration-neoforge/src/main/java/com/refinedmods/refinedstorage/rei/forge/PatternGridTransferHandler.java rename refinedstorage-rei-integration-neoforge/src/main/java/com/refinedmods/refinedstorage/rei/forge/{DraggableStackVisitorImpl.java => ResourceDraggableStackVisitor.java} (60%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f3a0bb..ee03cb0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Added + +- Grouping support for the Pattern Grid. +- Recipe transfer support for the Pattern Grid. + ## [0.2.2] - 2024-07-26 ### Fixed diff --git a/README.md b/README.md index a9f7768..dfcd41a 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 - Collapsable entries - Grid / REI search box synchronization diff --git a/gradle.properties b/gradle.properties index 237b909..7b9336a 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 # https://linkie.shedaniel.dev/dependencies?loader=neoforge&version=1.21 # https://linkie.shedaniel.dev/dependencies?loader=fabric&version=1.21 architecturyVersion=13.0.3 diff --git a/refinedstorage-rei-integration-fabric/src/main/java/com/refinedmods/refinedstorage/rei/fabric/CraftingGridTransferHandler.java b/refinedstorage-rei-integration-fabric/src/main/java/com/refinedmods/refinedstorage/rei/fabric/CraftingGridTransferHandler.java index 7671db3..06701d2 100644 --- a/refinedstorage-rei-integration-fabric/src/main/java/com/refinedmods/refinedstorage/rei/fabric/CraftingGridTransferHandler.java +++ b/refinedstorage-rei-integration-fabric/src/main/java/com/refinedmods/refinedstorage/rei/fabric/CraftingGridTransferHandler.java @@ -14,23 +14,22 @@ import me.shedaniel.rei.api.client.gui.widgets.Widget; import me.shedaniel.rei.api.client.registry.transfer.TransferHandler; import me.shedaniel.rei.api.client.registry.transfer.TransferHandlerRenderer; -import me.shedaniel.rei.api.common.category.CategoryIdentifier; import me.shedaniel.rei.api.common.entry.EntryIngredient; import me.shedaniel.rei.api.common.entry.EntryStack; import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes; import me.shedaniel.rei.api.common.util.CollectionUtils; +import me.shedaniel.rei.plugin.common.BuiltinPlugin; import me.shedaniel.rei.plugin.common.displays.crafting.DefaultCraftingDisplay; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.world.item.ItemStack; class CraftingGridTransferHandler implements TransferHandler { private static final Color MISSING_COLOR = new Color(1.0f, 0.0f, 0.0f, 0.4f); - private static final CategoryIdentifier CRAFTING = CategoryIdentifier.of("minecraft", "plugins/crafting"); @Override public Result handle(final Context context) { if (!(context.getMenu() instanceof CraftingGridContainerMenu containerMenu) - || !context.getDisplay().getCategoryIdentifier().equals(CRAFTING) + || !context.getDisplay().getCategoryIdentifier().equals(BuiltinPlugin.CRAFTING) || !(context.getDisplay() instanceof DefaultCraftingDisplay defaultCraftingDisplay)) { return Result.createNotApplicable(); } diff --git a/refinedstorage-rei-integration-fabric/src/main/java/com/refinedmods/refinedstorage/rei/fabric/FilterDraggableStackVisitor.java b/refinedstorage-rei-integration-fabric/src/main/java/com/refinedmods/refinedstorage/rei/fabric/FilterDraggableStackVisitor.java new file mode 100644 index 0000000..497bb73 --- /dev/null +++ b/refinedstorage-rei-integration-fabric/src/main/java/com/refinedmods/refinedstorage/rei/fabric/FilterDraggableStackVisitor.java @@ -0,0 +1,98 @@ +package com.refinedmods.refinedstorage.rei.fabric; + +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 java.util.ArrayList; +import java.util.List; +import java.util.stream.Stream; + +import me.shedaniel.math.Rectangle; +import me.shedaniel.rei.api.client.gui.drag.DraggableStack; +import me.shedaniel.rei.api.client.gui.drag.DraggableStackVisitor; +import me.shedaniel.rei.api.client.gui.drag.DraggedAcceptorResult; +import me.shedaniel.rei.api.client.gui.drag.DraggingContext; +import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; + +class FilterDraggableStackVisitor + implements DraggableStackVisitor> { + @Override + public Stream getDraggableAcceptingBounds( + final DraggingContext> context, + final DraggableStack stack + ) { + final var screen = context.getScreen(); + final var menu = screen.getMenu(); + final List bounds = new ArrayList<>(); + if (stack.getStack().getType() == VanillaEntryTypes.ITEM) { + addSlotBounds(stack, menu, bounds, screen); + } + return bounds.stream(); + } + + private void addSlotBounds( + final DraggableStack stack, + final AbstractBaseContainerMenu menu, + final List bounds, + final AbstractBaseScreen screen + ) { + final ItemStack itemStack = (ItemStack) stack.getStack().getValue(); + for (final Slot slot : menu.slots) { + if (slot instanceof FilterSlot filterSlot && isValid(itemStack, filterSlot)) { + bounds.add(BoundsProvider.ofRectangle(toRectangle(screen, slot))); + } + } + } + + @Override + public DraggedAcceptorResult acceptDraggedStack( + final DraggingContext> context, + final DraggableStack stack + ) { + final var screen = context.getScreen(); + final var menu = screen.getMenu(); + if (stack.getStack().getValue() instanceof ItemStack itemStack) { + return accept(context, menu, screen, itemStack); + } + return DraggedAcceptorResult.PASS; + } + + private DraggedAcceptorResult accept( + final DraggingContext> context, + final AbstractBaseContainerMenu menu, + final AbstractBaseScreen screen, + final ItemStack stack + ) { + for (final Slot slot : menu.slots) { + if (slot instanceof FilterSlot filterSlot && isValid(stack, filterSlot)) { + final Rectangle slotBounds = toRectangle(screen, slot); + if (!slotBounds.contains(context.getCurrentPosition())) { + continue; + } + C2SPackets.sendFilterSlotChange(stack, filterSlot.index); + return DraggedAcceptorResult.ACCEPTED; + } + } + return DraggedAcceptorResult.PASS; + } + + private static boolean isValid(final ItemStack stack, final FilterSlot slot) { + return slot.isActive() && slot.mayPlace(stack); + } + + private static Rectangle toRectangle(final AbstractBaseScreen screen, + final Slot slot) { + return new Rectangle(screen.getLeftPos() + slot.x, screen.getTopPos() + slot.y, 18, 18); + } + + @Override + public boolean isHandingScreen(final R screen) { + return screen instanceof AbstractBaseScreen + && ((AbstractBaseScreen) screen).getMenu() instanceof AbstractBaseContainerMenu; + } +} diff --git a/refinedstorage-rei-integration-fabric/src/main/java/com/refinedmods/refinedstorage/rei/fabric/GridFocusedStackProvider.java b/refinedstorage-rei-integration-fabric/src/main/java/com/refinedmods/refinedstorage/rei/fabric/GridFocusedStackProvider.java index 7c99d3b..f98c457 100644 --- a/refinedstorage-rei-integration-fabric/src/main/java/com/refinedmods/refinedstorage/rei/fabric/GridFocusedStackProvider.java +++ b/refinedstorage-rei-integration-fabric/src/main/java/com/refinedmods/refinedstorage/rei/fabric/GridFocusedStackProvider.java @@ -21,7 +21,7 @@ public CompoundEventResult> provide(final Screen screen, final Poi if (resource == null) { return CompoundEventResult.pass(); } - final PlatformResourceKey underlyingResource = resource.getUnderlyingResource(); + final PlatformResourceKey underlyingResource = resource.getResourceForRecipeMods(); if (underlyingResource == null) { return CompoundEventResult.pass(); } diff --git a/refinedstorage-rei-integration-fabric/src/main/java/com/refinedmods/refinedstorage/rei/fabric/PatternGridTransferHandler.java b/refinedstorage-rei-integration-fabric/src/main/java/com/refinedmods/refinedstorage/rei/fabric/PatternGridTransferHandler.java new file mode 100644 index 0000000..49b4d7e --- /dev/null +++ b/refinedstorage-rei-integration-fabric/src/main/java/com/refinedmods/refinedstorage/rei/fabric/PatternGridTransferHandler.java @@ -0,0 +1,113 @@ +package com.refinedmods.refinedstorage.rei.fabric; + +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 javax.annotation.Nullable; + +import me.shedaniel.rei.api.client.registry.transfer.TransferHandler; +import me.shedaniel.rei.api.common.entry.EntryIngredient; +import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes; +import me.shedaniel.rei.api.common.util.CollectionUtils; +import me.shedaniel.rei.plugin.common.BuiltinPlugin; +import me.shedaniel.rei.plugin.common.displays.crafting.DefaultCraftingDisplay; +import net.minecraft.world.item.ItemStack; + +class PatternGridTransferHandler implements TransferHandler { + @Override + public Result handle(final Context context) { + if (!(context.getMenu() instanceof PatternGridContainerMenu containerMenu)) { + return Result.createNotApplicable(); + } + final Result result = transferRegularRecipe(context, containerMenu); + if (result != null) { + return result; + } + return transferProcessingRecipe(context, containerMenu); + } + + @Nullable + private Result transferRegularRecipe(final Context context, final PatternGridContainerMenu containerMenu) { + if (context.getDisplay().getCategoryIdentifier().equals(BuiltinPlugin.CRAFTING) + && context.getDisplay() instanceof DefaultCraftingDisplay defaultCraftingDisplay) { + return transferCraftingRecipe(context, containerMenu, defaultCraftingDisplay); + } else if (context.getDisplay().getCategoryIdentifier().equals(BuiltinPlugin.STONE_CUTTING)) { + return transferStonecutterRecipe(context, containerMenu); + } else if (context.getDisplay().getCategoryIdentifier().equals(BuiltinPlugin.SMITHING)) { + return transferSmithingTableRecipe(context, containerMenu); + } + return null; + } + + private Result transferCraftingRecipe(final Context context, + final PatternGridContainerMenu containerMenu, + final DefaultCraftingDisplay display) { + final List> inputs = getItems( + display.getOrganisedInputEntries(3, 3) + ); + if (context.isActuallyCrafting()) { + containerMenu.transferCraftingRecipe(inputs); + } + return Result.createSuccessful().blocksFurtherHandling(); + } + + private Result transferStonecutterRecipe(final Context context, final PatternGridContainerMenu menu) { + final List> inputs = getItems(context.getDisplay().getInputEntries()); + final List> outputs = getItems(context.getDisplay().getOutputEntries()); + final boolean valid = !inputs.isEmpty() + && !outputs.isEmpty() + && !inputs.getFirst().isEmpty() + && !outputs.getFirst().isEmpty(); + if (context.isActuallyCrafting() && valid) { + menu.transferStonecutterRecipe(inputs.getFirst().getFirst(), outputs.getFirst().getFirst()); + } + return Result.createSuccessful().blocksFurtherHandling(); + } + + private Result transferSmithingTableRecipe(final Context context, final PatternGridContainerMenu menu) { + final List> inputs = getItems(context.getDisplay().getInputEntries()); + if (context.isActuallyCrafting() && inputs.size() == 3) { + menu.transferSmithingTableRecipe(inputs.get(0), inputs.get(1), inputs.get(2)); + } + return Result.createSuccessful().blocksFurtherHandling(); + } + + private Result transferProcessingRecipe(final Context context, final PatternGridContainerMenu menu) { + final List> inputs = getResources(context.getDisplay().getInputEntries()); + final List> outputs = getResources(context.getDisplay().getOutputEntries()); + if (context.isActuallyCrafting()) { + menu.transferProcessingRecipe(inputs, outputs); + } + return Result.createSuccessful().blocksFurtherHandling(); + } + + private List> getItems(final List ingredients) { + return ingredients.stream() + .map(this::convertIngredientToItemStacks) + .map(list -> list.stream().map(ItemResource::ofItemStack).collect(Collectors.toList())) + .toList(); + } + + private List convertIngredientToItemStacks(final EntryIngredient ingredient) { + return CollectionUtils., ItemStack>filterAndMap( + ingredient, + stack -> stack.getType() == VanillaEntryTypes.ITEM, + EntryStack::castValue + ); + } + + private List> getResources(final List ingredients) { + return ingredients.stream() + .map(ingredient -> ingredient.stream() + .flatMap( + item -> RefinedStorageApi.INSTANCE.getIngredientConverter().convertToResourceAmount(item.getValue()) + .stream()) + .collect(Collectors.toList())) + .toList(); + } +} diff --git a/refinedstorage-rei-integration-fabric/src/main/java/com/refinedmods/refinedstorage/rei/fabric/ReiClientPlugin.java b/refinedstorage-rei-integration-fabric/src/main/java/com/refinedmods/refinedstorage/rei/fabric/ReiClientPlugin.java index a5809e0..04b841c 100644 --- a/refinedstorage-rei-integration-fabric/src/main/java/com/refinedmods/refinedstorage/rei/fabric/ReiClientPlugin.java +++ b/refinedstorage-rei-integration-fabric/src/main/java/com/refinedmods/refinedstorage/rei/fabric/ReiClientPlugin.java @@ -33,12 +33,14 @@ public class ReiClientPlugin implements REIClientPlugin { public void registerScreens(final ScreenRegistry registry) { registry.registerFocusedStack(new GridFocusedStackProvider()); registry.registerFocusedStack(new ResourceFocusedStackProvider()); - registry.registerDraggableStackVisitor(new DraggableStackVisitorImpl()); + registry.registerDraggableStackVisitor(new ResourceDraggableStackVisitor()); + registry.registerDraggableStackVisitor(new FilterDraggableStackVisitor()); } @Override public void registerTransferHandlers(final TransferHandlerRegistry registry) { registry.register(new CraftingGridTransferHandler()); + registry.register(new PatternGridTransferHandler()); } @Override @@ -55,6 +57,7 @@ private Component tagName(final String name) { public void registerCollapsibleEntries(final CollapsibleEntryRegistry registry) { groupItems(registry, tagName("cables"), ContentIds.CABLE, Tags.CABLES); groupItems(registry, tagName("grids"), ContentIds.GRID, Tags.GRIDS); + groupItems(registry, tagName("pattern_grids"), ContentIds.PATTERN_GRID, Tags.PATTERN_GRIDS); groupItems(registry, tagName("crafting_grids"), ContentIds.CRAFTING_GRID, Tags.CRAFTING_GRIDS); groupItems(registry, tagName("importers"), ContentIds.IMPORTER, Tags.IMPORTERS); groupItems(registry, tagName("exporters"), ContentIds.EXPORTER, Tags.EXPORTERS); diff --git a/refinedstorage-rei-integration-fabric/src/main/java/com/refinedmods/refinedstorage/rei/fabric/ReiRecipeModIngredientConverter.java b/refinedstorage-rei-integration-fabric/src/main/java/com/refinedmods/refinedstorage/rei/fabric/ReiRecipeModIngredientConverter.java index 074b036..3695f33 100644 --- a/refinedstorage-rei-integration-fabric/src/main/java/com/refinedmods/refinedstorage/rei/fabric/ReiRecipeModIngredientConverter.java +++ b/refinedstorage-rei-integration-fabric/src/main/java/com/refinedmods/refinedstorage/rei/fabric/ReiRecipeModIngredientConverter.java @@ -1,5 +1,6 @@ package com.refinedmods.refinedstorage.rei.fabric; +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; @@ -23,6 +24,23 @@ public Optional convertToResource(final Object ingredient) return Optional.empty(); } + @Override + public Optional convertToResourceAmount(final Object ingredient) { + if (ingredient instanceof FluidStack fluidStack) { + return Optional.of(new ResourceAmount( + new FluidResource(fluidStack.getFluid(), fluidStack.getPatch()), + fluidStack.getAmount() + )); + } + if (ingredient instanceof ItemStack itemStack) { + return Optional.of(new ResourceAmount( + ItemResource.ofItemStack(itemStack), + itemStack.getCount() + )); + } + return Optional.empty(); + } + @Override public Optional convertToIngredient(final PlatformResourceKey resource) { if (resource instanceof ItemResource itemResource) { diff --git a/refinedstorage-rei-integration-fabric/src/main/java/com/refinedmods/refinedstorage/rei/fabric/ResourceDraggableStackVisitor.java b/refinedstorage-rei-integration-fabric/src/main/java/com/refinedmods/refinedstorage/rei/fabric/ResourceDraggableStackVisitor.java new file mode 100644 index 0000000..ef40de4 --- /dev/null +++ b/refinedstorage-rei-integration-fabric/src/main/java/com/refinedmods/refinedstorage/rei/fabric/ResourceDraggableStackVisitor.java @@ -0,0 +1,100 @@ +package com.refinedmods.refinedstorage.rei.fabric; + +import com.refinedmods.refinedstorage.common.api.RefinedStorageApi; +import com.refinedmods.refinedstorage.common.api.support.resource.PlatformResourceKey; +import com.refinedmods.refinedstorage.common.support.AbstractBaseContainerMenu; +import com.refinedmods.refinedstorage.common.support.AbstractBaseScreen; +import com.refinedmods.refinedstorage.common.support.containermenu.AbstractResourceContainerMenu; +import com.refinedmods.refinedstorage.common.support.containermenu.ResourceSlot; +import com.refinedmods.refinedstorage.common.support.packet.c2s.C2SPackets; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Stream; + +import me.shedaniel.math.Rectangle; +import me.shedaniel.rei.api.client.gui.drag.DraggableStack; +import me.shedaniel.rei.api.client.gui.drag.DraggableStackVisitor; +import me.shedaniel.rei.api.client.gui.drag.DraggedAcceptorResult; +import me.shedaniel.rei.api.client.gui.drag.DraggingContext; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.world.inventory.Slot; + +class ResourceDraggableStackVisitor + implements DraggableStackVisitor> { + @Override + public Stream getDraggableAcceptingBounds( + final DraggingContext> context, + final DraggableStack stack + ) { + final var screen = context.getScreen(); + final var menu = screen.getMenu(); + final var value = stack.getStack().getValue(); + final List bounds = new ArrayList<>(); + if (menu instanceof AbstractResourceContainerMenu resourceMenu) { + addSlotBounds(resourceMenu, value, bounds, screen); + } + return bounds.stream(); + } + + private void addSlotBounds( + final AbstractResourceContainerMenu resourceMenu, + final Object value, + final List bounds, + final AbstractBaseScreen screen + ) { + RefinedStorageApi.INSTANCE.getIngredientConverter().convertToResource(value).ifPresent(resource -> { + for (final ResourceSlot slot : resourceMenu.getResourceSlots()) { + if (isValid(resource, slot)) { + bounds.add(BoundsProvider.ofRectangle(toRectangle(screen, slot))); + } + } + }); + } + + @Override + public DraggedAcceptorResult acceptDraggedStack( + final DraggingContext> context, + final DraggableStack stack + ) { + final var screen = context.getScreen(); + final var menu = screen.getMenu(); + final Object stackValue = stack.getStack().getValue(); + return RefinedStorageApi.INSTANCE.getIngredientConverter().convertToResource(stackValue) + .map(resource -> accept(context, menu, screen, resource)) + .orElse(DraggedAcceptorResult.PASS); + } + + private DraggedAcceptorResult accept( + final DraggingContext> context, + final AbstractBaseContainerMenu menu, + final AbstractBaseScreen screen, + final PlatformResourceKey resource + ) { + if (menu instanceof AbstractResourceContainerMenu resourceMenu) { + for (final ResourceSlot slot : resourceMenu.getResourceSlots()) { + final Rectangle slotBounds = toRectangle(screen, slot); + if (isValid(resource, slot) && slotBounds.contains(context.getCurrentPosition())) { + C2SPackets.sendResourceFilterSlotChange(resource, slot.index); + return DraggedAcceptorResult.ACCEPTED; + } + } + } + return DraggedAcceptorResult.PASS; + } + + private static boolean isValid(final PlatformResourceKey resource, final ResourceSlot slot) { + return slot.isFilter() && slot.isActive() && slot.isValid(resource); + } + + private static Rectangle toRectangle(final AbstractBaseScreen screen, + final Slot slot) { + return new Rectangle(screen.getLeftPos() + slot.x, screen.getTopPos() + slot.y, 18, 18); + } + + @Override + public boolean isHandingScreen(final R screen) { + return screen instanceof AbstractBaseScreen + && ((AbstractBaseScreen) screen).getMenu() instanceof AbstractResourceContainerMenu; + } +} diff --git a/refinedstorage-rei-integration-neoforge/src/main/java/com/refinedmods/refinedstorage/rei/forge/CraftingGridTransferHandler.java b/refinedstorage-rei-integration-neoforge/src/main/java/com/refinedmods/refinedstorage/rei/forge/CraftingGridTransferHandler.java index f32f35c..f37db46 100644 --- a/refinedstorage-rei-integration-neoforge/src/main/java/com/refinedmods/refinedstorage/rei/forge/CraftingGridTransferHandler.java +++ b/refinedstorage-rei-integration-neoforge/src/main/java/com/refinedmods/refinedstorage/rei/forge/CraftingGridTransferHandler.java @@ -14,23 +14,22 @@ import me.shedaniel.rei.api.client.gui.widgets.Widget; import me.shedaniel.rei.api.client.registry.transfer.TransferHandler; import me.shedaniel.rei.api.client.registry.transfer.TransferHandlerRenderer; -import me.shedaniel.rei.api.common.category.CategoryIdentifier; import me.shedaniel.rei.api.common.entry.EntryIngredient; import me.shedaniel.rei.api.common.entry.EntryStack; import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes; import me.shedaniel.rei.api.common.util.CollectionUtils; +import me.shedaniel.rei.plugin.common.BuiltinPlugin; import me.shedaniel.rei.plugin.common.displays.crafting.DefaultCraftingDisplay; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.world.item.ItemStack; class CraftingGridTransferHandler implements TransferHandler { private static final Color MISSING_COLOR = new Color(1.0f, 0.0f, 0.0f, 0.4f); - private static final CategoryIdentifier CRAFTING = CategoryIdentifier.of("minecraft", "plugins/crafting"); @Override public Result handle(final Context context) { if (!(context.getMenu() instanceof CraftingGridContainerMenu containerMenu) - || !context.getDisplay().getCategoryIdentifier().equals(CRAFTING) + || !context.getDisplay().getCategoryIdentifier().equals(BuiltinPlugin.CRAFTING) || !(context.getDisplay() instanceof DefaultCraftingDisplay defaultCraftingDisplay)) { return Result.createNotApplicable(); } diff --git a/refinedstorage-rei-integration-neoforge/src/main/java/com/refinedmods/refinedstorage/rei/forge/FilterDraggableStackVisitor.java b/refinedstorage-rei-integration-neoforge/src/main/java/com/refinedmods/refinedstorage/rei/forge/FilterDraggableStackVisitor.java new file mode 100644 index 0000000..c827adb --- /dev/null +++ b/refinedstorage-rei-integration-neoforge/src/main/java/com/refinedmods/refinedstorage/rei/forge/FilterDraggableStackVisitor.java @@ -0,0 +1,98 @@ +package com.refinedmods.refinedstorage.rei.forge; + +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 java.util.ArrayList; +import java.util.List; +import java.util.stream.Stream; + +import me.shedaniel.math.Rectangle; +import me.shedaniel.rei.api.client.gui.drag.DraggableStack; +import me.shedaniel.rei.api.client.gui.drag.DraggableStackVisitor; +import me.shedaniel.rei.api.client.gui.drag.DraggedAcceptorResult; +import me.shedaniel.rei.api.client.gui.drag.DraggingContext; +import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; + +class FilterDraggableStackVisitor + implements DraggableStackVisitor> { + @Override + public Stream getDraggableAcceptingBounds( + final DraggingContext> context, + final DraggableStack stack + ) { + final var screen = context.getScreen(); + final var menu = screen.getMenu(); + final List bounds = new ArrayList<>(); + if (stack.getStack().getType() == VanillaEntryTypes.ITEM) { + addSlotBounds(stack, menu, bounds, screen); + } + return bounds.stream(); + } + + private void addSlotBounds( + final DraggableStack stack, + final AbstractBaseContainerMenu menu, + final List bounds, + final AbstractBaseScreen screen + ) { + final ItemStack itemStack = (ItemStack) stack.getStack().getValue(); + for (final Slot slot : menu.slots) { + if (slot instanceof FilterSlot filterSlot && isValid(itemStack, filterSlot)) { + bounds.add(BoundsProvider.ofRectangle(toRectangle(screen, slot))); + } + } + } + + @Override + public DraggedAcceptorResult acceptDraggedStack( + final DraggingContext> context, + final DraggableStack stack + ) { + final var screen = context.getScreen(); + final var menu = screen.getMenu(); + if (stack.getStack().getValue() instanceof ItemStack itemStack) { + return accept(context, menu, screen, itemStack); + } + return DraggedAcceptorResult.PASS; + } + + private DraggedAcceptorResult accept( + final DraggingContext> context, + final AbstractBaseContainerMenu menu, + final AbstractBaseScreen screen, + final ItemStack stack + ) { + for (final Slot slot : menu.slots) { + if (slot instanceof FilterSlot filterSlot && isValid(stack, filterSlot)) { + final Rectangle slotBounds = toRectangle(screen, slot); + if (!slotBounds.contains(context.getCurrentPosition())) { + continue; + } + C2SPackets.sendFilterSlotChange(stack, filterSlot.index); + return DraggedAcceptorResult.ACCEPTED; + } + } + return DraggedAcceptorResult.PASS; + } + + private static boolean isValid(final ItemStack stack, final FilterSlot slot) { + return slot.isActive() && slot.mayPlace(stack); + } + + private static Rectangle toRectangle(final AbstractBaseScreen screen, + final Slot slot) { + return new Rectangle(screen.getLeftPos() + slot.x, screen.getTopPos() + slot.y, 18, 18); + } + + @Override + public boolean isHandingScreen(final R screen) { + return screen instanceof AbstractBaseScreen + && ((AbstractBaseScreen) screen).getMenu() instanceof AbstractBaseContainerMenu; + } +} diff --git a/refinedstorage-rei-integration-neoforge/src/main/java/com/refinedmods/refinedstorage/rei/forge/GridFocusedStackProvider.java b/refinedstorage-rei-integration-neoforge/src/main/java/com/refinedmods/refinedstorage/rei/forge/GridFocusedStackProvider.java index c5cbc2c..fbc4c02 100644 --- a/refinedstorage-rei-integration-neoforge/src/main/java/com/refinedmods/refinedstorage/rei/forge/GridFocusedStackProvider.java +++ b/refinedstorage-rei-integration-neoforge/src/main/java/com/refinedmods/refinedstorage/rei/forge/GridFocusedStackProvider.java @@ -21,7 +21,7 @@ public CompoundEventResult> provide(final Screen screen, final Poi if (resource == null) { return CompoundEventResult.pass(); } - final PlatformResourceKey underlyingResource = resource.getUnderlyingResource(); + final PlatformResourceKey underlyingResource = resource.getResourceForRecipeMods(); if (underlyingResource == null) { return CompoundEventResult.pass(); } diff --git a/refinedstorage-rei-integration-neoforge/src/main/java/com/refinedmods/refinedstorage/rei/forge/PatternGridTransferHandler.java b/refinedstorage-rei-integration-neoforge/src/main/java/com/refinedmods/refinedstorage/rei/forge/PatternGridTransferHandler.java new file mode 100644 index 0000000..c111dc6 --- /dev/null +++ b/refinedstorage-rei-integration-neoforge/src/main/java/com/refinedmods/refinedstorage/rei/forge/PatternGridTransferHandler.java @@ -0,0 +1,113 @@ +package com.refinedmods.refinedstorage.rei.forge; + +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 javax.annotation.Nullable; + +import me.shedaniel.rei.api.client.registry.transfer.TransferHandler; +import me.shedaniel.rei.api.common.entry.EntryIngredient; +import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes; +import me.shedaniel.rei.api.common.util.CollectionUtils; +import me.shedaniel.rei.plugin.common.BuiltinPlugin; +import me.shedaniel.rei.plugin.common.displays.crafting.DefaultCraftingDisplay; +import net.minecraft.world.item.ItemStack; + +class PatternGridTransferHandler implements TransferHandler { + @Override + public Result handle(final Context context) { + if (!(context.getMenu() instanceof PatternGridContainerMenu containerMenu)) { + return Result.createNotApplicable(); + } + final Result result = transferRegularRecipe(context, containerMenu); + if (result != null) { + return result; + } + return transferProcessingRecipe(context, containerMenu); + } + + @Nullable + private Result transferRegularRecipe(final Context context, final PatternGridContainerMenu containerMenu) { + if (context.getDisplay().getCategoryIdentifier().equals(BuiltinPlugin.CRAFTING) + && context.getDisplay() instanceof DefaultCraftingDisplay defaultCraftingDisplay) { + return transferCraftingRecipe(context, containerMenu, defaultCraftingDisplay); + } else if (context.getDisplay().getCategoryIdentifier().equals(BuiltinPlugin.STONE_CUTTING)) { + return transferStonecutterRecipe(context, containerMenu); + } else if (context.getDisplay().getCategoryIdentifier().equals(BuiltinPlugin.SMITHING)) { + return transferSmithingTableRecipe(context, containerMenu); + } + return null; + } + + private Result transferCraftingRecipe(final Context context, + final PatternGridContainerMenu containerMenu, + final DefaultCraftingDisplay display) { + final List> inputs = getItems( + display.getOrganisedInputEntries(3, 3) + ); + if (context.isActuallyCrafting()) { + containerMenu.transferCraftingRecipe(inputs); + } + return Result.createSuccessful().blocksFurtherHandling(); + } + + private Result transferStonecutterRecipe(final Context context, final PatternGridContainerMenu menu) { + final List> inputs = getItems(context.getDisplay().getInputEntries()); + final List> outputs = getItems(context.getDisplay().getOutputEntries()); + final boolean valid = !inputs.isEmpty() + && !outputs.isEmpty() + && !inputs.getFirst().isEmpty() + && !outputs.getFirst().isEmpty(); + if (context.isActuallyCrafting() && valid) { + menu.transferStonecutterRecipe(inputs.getFirst().getFirst(), outputs.getFirst().getFirst()); + } + return Result.createSuccessful().blocksFurtherHandling(); + } + + private Result transferSmithingTableRecipe(final Context context, final PatternGridContainerMenu menu) { + final List> inputs = getItems(context.getDisplay().getInputEntries()); + if (context.isActuallyCrafting() && inputs.size() == 3) { + menu.transferSmithingTableRecipe(inputs.get(0), inputs.get(1), inputs.get(2)); + } + return Result.createSuccessful().blocksFurtherHandling(); + } + + private Result transferProcessingRecipe(final Context context, final PatternGridContainerMenu menu) { + final List> inputs = getResources(context.getDisplay().getInputEntries()); + final List> outputs = getResources(context.getDisplay().getOutputEntries()); + if (context.isActuallyCrafting()) { + menu.transferProcessingRecipe(inputs, outputs); + } + return Result.createSuccessful().blocksFurtherHandling(); + } + + private List> getItems(final List ingredients) { + return ingredients.stream() + .map(this::convertIngredientToItemStacks) + .map(list -> list.stream().map(ItemResource::ofItemStack).collect(Collectors.toList())) + .toList(); + } + + private List convertIngredientToItemStacks(final EntryIngredient ingredient) { + return CollectionUtils., ItemStack>filterAndMap( + ingredient, + stack -> stack.getType() == VanillaEntryTypes.ITEM, + EntryStack::castValue + ); + } + + private List> getResources(final List ingredients) { + return ingredients.stream() + .map(ingredient -> ingredient.stream() + .flatMap( + item -> RefinedStorageApi.INSTANCE.getIngredientConverter().convertToResourceAmount(item.getValue()) + .stream()) + .collect(Collectors.toList())) + .toList(); + } +} diff --git a/refinedstorage-rei-integration-neoforge/src/main/java/com/refinedmods/refinedstorage/rei/forge/ReiClientPlugin.java b/refinedstorage-rei-integration-neoforge/src/main/java/com/refinedmods/refinedstorage/rei/forge/ReiClientPlugin.java index 0a7a760..acf739f 100644 --- a/refinedstorage-rei-integration-neoforge/src/main/java/com/refinedmods/refinedstorage/rei/forge/ReiClientPlugin.java +++ b/refinedstorage-rei-integration-neoforge/src/main/java/com/refinedmods/refinedstorage/rei/forge/ReiClientPlugin.java @@ -32,12 +32,14 @@ public class ReiClientPlugin implements REIClientPlugin { public void registerScreens(final ScreenRegistry registry) { registry.registerFocusedStack(new GridFocusedStackProvider()); registry.registerFocusedStack(new ResourceFocusedStackProvider()); - registry.registerDraggableStackVisitor(new DraggableStackVisitorImpl()); + registry.registerDraggableStackVisitor(new ResourceDraggableStackVisitor()); + registry.registerDraggableStackVisitor(new FilterDraggableStackVisitor()); } @Override public void registerTransferHandlers(final TransferHandlerRegistry registry) { registry.register(new CraftingGridTransferHandler()); + registry.register(new PatternGridTransferHandler()); } @Override @@ -54,6 +56,7 @@ private Component tagName(final String name) { public void registerCollapsibleEntries(final CollapsibleEntryRegistry registry) { groupItems(registry, tagName("cables"), ContentIds.CABLE, Tags.CABLES); groupItems(registry, tagName("grids"), ContentIds.GRID, Tags.GRIDS); + groupItems(registry, tagName("pattern_grids"), ContentIds.PATTERN_GRID, Tags.PATTERN_GRIDS); groupItems(registry, tagName("crafting_grids"), ContentIds.CRAFTING_GRID, Tags.CRAFTING_GRIDS); groupItems(registry, tagName("importers"), ContentIds.IMPORTER, Tags.IMPORTERS); groupItems(registry, tagName("exporters"), ContentIds.EXPORTER, Tags.EXPORTERS); diff --git a/refinedstorage-rei-integration-neoforge/src/main/java/com/refinedmods/refinedstorage/rei/forge/ReiRecipeModIngredientConverter.java b/refinedstorage-rei-integration-neoforge/src/main/java/com/refinedmods/refinedstorage/rei/forge/ReiRecipeModIngredientConverter.java index 6f36a29..5d13fcb 100644 --- a/refinedstorage-rei-integration-neoforge/src/main/java/com/refinedmods/refinedstorage/rei/forge/ReiRecipeModIngredientConverter.java +++ b/refinedstorage-rei-integration-neoforge/src/main/java/com/refinedmods/refinedstorage/rei/forge/ReiRecipeModIngredientConverter.java @@ -1,5 +1,6 @@ package com.refinedmods.refinedstorage.rei.forge; +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; @@ -23,6 +24,23 @@ public Optional convertToResource(final Object ingredient) return Optional.empty(); } + @Override + public Optional convertToResourceAmount(final Object ingredient) { + if (ingredient instanceof FluidStack fluidStack) { + return Optional.of(new ResourceAmount( + new FluidResource(fluidStack.getFluid(), fluidStack.getPatch()), + fluidStack.getAmount() + )); + } + if (ingredient instanceof ItemStack itemStack) { + return Optional.of(new ResourceAmount( + ItemResource.ofItemStack(itemStack), + itemStack.getCount() + )); + } + return Optional.empty(); + } + @Override public Optional convertToIngredient(final PlatformResourceKey resource) { if (resource instanceof ItemResource itemResource) { diff --git a/refinedstorage-rei-integration-neoforge/src/main/java/com/refinedmods/refinedstorage/rei/forge/DraggableStackVisitorImpl.java b/refinedstorage-rei-integration-neoforge/src/main/java/com/refinedmods/refinedstorage/rei/forge/ResourceDraggableStackVisitor.java similarity index 60% rename from refinedstorage-rei-integration-neoforge/src/main/java/com/refinedmods/refinedstorage/rei/forge/DraggableStackVisitorImpl.java rename to refinedstorage-rei-integration-neoforge/src/main/java/com/refinedmods/refinedstorage/rei/forge/ResourceDraggableStackVisitor.java index 5375f9b..02ff887 100644 --- a/refinedstorage-rei-integration-neoforge/src/main/java/com/refinedmods/refinedstorage/rei/forge/DraggableStackVisitorImpl.java +++ b/refinedstorage-rei-integration-neoforge/src/main/java/com/refinedmods/refinedstorage/rei/forge/ResourceDraggableStackVisitor.java @@ -2,6 +2,7 @@ import com.refinedmods.refinedstorage.common.api.RefinedStorageApi; import com.refinedmods.refinedstorage.common.api.support.resource.PlatformResourceKey; +import com.refinedmods.refinedstorage.common.support.AbstractBaseContainerMenu; import com.refinedmods.refinedstorage.common.support.AbstractBaseScreen; import com.refinedmods.refinedstorage.common.support.containermenu.AbstractResourceContainerMenu; import com.refinedmods.refinedstorage.common.support.containermenu.ResourceSlot; @@ -17,60 +18,77 @@ import me.shedaniel.rei.api.client.gui.drag.DraggedAcceptorResult; import me.shedaniel.rei.api.client.gui.drag.DraggingContext; import net.minecraft.client.gui.screens.Screen; +import net.minecraft.world.inventory.Slot; -class DraggableStackVisitorImpl - implements DraggableStackVisitor> { +class ResourceDraggableStackVisitor + implements DraggableStackVisitor> { @Override public Stream getDraggableAcceptingBounds( - final DraggingContext> context, + final DraggingContext> context, final DraggableStack stack ) { final var screen = context.getScreen(); final var menu = screen.getMenu(); final var value = stack.getStack().getValue(); final List bounds = new ArrayList<>(); + if (menu instanceof AbstractResourceContainerMenu resourceMenu) { + addSlotBounds(resourceMenu, value, bounds, screen); + } + return bounds.stream(); + } + + private void addSlotBounds( + final AbstractResourceContainerMenu resourceMenu, + final Object value, + final List bounds, + final AbstractBaseScreen screen + ) { RefinedStorageApi.INSTANCE.getIngredientConverter().convertToResource(value).ifPresent(resource -> { - for (final ResourceSlot slot : menu.getResourceSlots()) { - if (slot.isFilter() && slot.isValid(resource)) { + for (final ResourceSlot slot : resourceMenu.getResourceSlots()) { + if (isValid(resource, slot)) { bounds.add(BoundsProvider.ofRectangle(toRectangle(screen, slot))); } } }); - return bounds.stream(); } @Override public DraggedAcceptorResult acceptDraggedStack( - final DraggingContext> context, + final DraggingContext> context, final DraggableStack stack ) { final var screen = context.getScreen(); final var menu = screen.getMenu(); - final Object value = stack.getStack().getValue(); - return RefinedStorageApi.INSTANCE.getIngredientConverter().convertToResource(value) + final Object stackValue = stack.getStack().getValue(); + return RefinedStorageApi.INSTANCE.getIngredientConverter().convertToResource(stackValue) .map(resource -> accept(context, menu, screen, resource)) .orElse(DraggedAcceptorResult.PASS); } private DraggedAcceptorResult accept( - final DraggingContext> context, - final AbstractResourceContainerMenu menu, - final AbstractBaseScreen screen, + final DraggingContext> context, + final AbstractBaseContainerMenu menu, + final AbstractBaseScreen screen, final PlatformResourceKey resource ) { - for (final ResourceSlot slot : menu.getResourceSlots()) { - final Rectangle slotBounds = toRectangle(screen, slot); - if (!slotBounds.contains(context.getCurrentPosition())) { - continue; + if (menu instanceof AbstractResourceContainerMenu resourceMenu) { + for (final ResourceSlot slot : resourceMenu.getResourceSlots()) { + final Rectangle slotBounds = toRectangle(screen, slot); + if (isValid(resource, slot) && slotBounds.contains(context.getCurrentPosition())) { + C2SPackets.sendResourceFilterSlotChange(resource, slot.index); + return DraggedAcceptorResult.ACCEPTED; + } } - C2SPackets.sendResourceFilterSlotChange(resource, slot.index); - return DraggedAcceptorResult.ACCEPTED; } return DraggedAcceptorResult.PASS; } - private static Rectangle toRectangle(final AbstractBaseScreen screen, - final ResourceSlot slot) { + private static boolean isValid(final PlatformResourceKey resource, final ResourceSlot slot) { + return slot.isFilter() && slot.isActive() && slot.isValid(resource); + } + + private static Rectangle toRectangle(final AbstractBaseScreen screen, + final Slot slot) { return new Rectangle(screen.getLeftPos() + slot.x, screen.getTopPos() + slot.y, 18, 18); } From 6cc6b8efb8885b0a0bbce419bb197a5514a10955 Mon Sep 17 00:00:00 2001 From: raoulvdberge Date: Thu, 8 Aug 2024 17:26:29 +0000 Subject: [PATCH 2/2] chore: prepare release v0.3.0 --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee03cb0..f771765 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +## [0.3.0] - 2024-08-08 + ### Added - Grouping support for the Pattern Grid. @@ -61,7 +63,9 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - Support for REI collapsable entries. - Grid / REI search box synchronization options. -[Unreleased]: https://github.com/refinedmods/refinedstorage-rei-integration/compare/v0.2.2...HEAD +[Unreleased]: https://github.com/refinedmods/refinedstorage-rei-integration/compare/v0.3.0...HEAD + +[0.3.0]: https://github.com/refinedmods/refinedstorage-rei-integration/compare/v0.2.2...v0.3.0 [0.2.2]: https://github.com/refinedmods/refinedstorage-rei-integration/compare/v0.2.1...v0.2.2