Compare commits

...

12 Commits

Author SHA1 Message Date
Salomão 76ae078d24 push patterns in round-robin 2021-04-29 21:19:07 -03:00
Salomão 0fae87afc7 allow left clicking on bookmarked items on GUIs without fake slots 2021-04-26 23:53:43 -03:00
Salomão ee1b6bb0d7 Add bookmarked ghost items support
fixed fluid dragging not working on servers
2021-04-18 21:01:09 -03:00
Salomão 36ca8b9f0a JEI Bookmark dragnDrop 2021-04-15 22:58:57 -03:00
Salomão 9c94c7342b Merge branch 'JEI-drag-phantom-items' into AE2-Omnifactory 2021-04-14 21:46:40 -03:00
Salomão 399d67b42c made jei recipe transfer more strict when keeping items on the table
few cleanup
2021-04-14 21:37:06 -03:00
Salomão 10761a1e9d missing click cancel 2021-04-14 00:04:07 -03:00
Salomão d1ddf53d99 wip 2 2021-04-13 14:54:52 -03:00
Salomão f776b4d548 wip 2021-04-13 12:36:20 -03:00
Salomão 41180792e1 Cellworkbench acts weird
missing bookmark dragging
2021-04-12 23:51:49 -03:00
Salomão 2269c05d98 implement #14
also fix tooltip position
2021-04-10 09:46:48 -03:00
Salomão 63616e5730 try fix #13 2021-04-10 09:30:44 -03:00
21 changed files with 735 additions and 78 deletions
-3
View File
@@ -85,7 +85,6 @@ configurations {
}
dependencies {
compileOnly "com.jaquadro.minecraft.storagedrawers:StorageDrawers:1.12.2-5.4.2:api"
compileOnly "gregtechce:gregtech:1.12.2:1.12.0.662"
// installable runtime dependencies
@@ -106,8 +105,6 @@ dependencies {
// at runtime, use the full JEI jar
runtime "mezz.jei:jei_${minecraft_version}:${jei_version}"
runtime "com.jaquadro.minecraft.storagedrawers:StorageDrawers:1.12.2-5.4.2"
runtime "com.jaquadro.minecraft.chameleon:Chameleon:1.12-4.1.3"
// unit test dependencies
testCompile "junit:junit:4.12"
@@ -0,0 +1,143 @@
package com.jaquadro.minecraft.storagedrawers.api.capabilities;
import net.minecraft.item.ItemStack;
import net.minecraft.util.NonNullList;
import javax.annotation.Nonnull;
import java.util.function.Predicate;
/**
* An interface for treating an inventory as a slotless, central repository of items.
*
* For all operations that accept a predicate, if a predicate is supplied, a stored ItemStack must pass the predicate
* in order to be considered for the given operation.
*
* An IItemRepository implementation MAY relax or eliminate its own internal tests when a predicate is supplied. If
* the predicate is derived from DefaultPredicate, then the implementation MUST apply any tests it would have applied
* had no predicate been provided at all, in addition to testing the predicate itself.
*/
public interface IItemRepository
{
/**
* Gets a list of all items in the inventory. The same item may appear multiple times with varying counts.
* @return A list of zero or more items in the inventory.
*/
@Nonnull
NonNullList<ItemRecord> getAllItems ();
/**
* Inserts an ItemStack into the inventory and returns the remainder.
*
* @param stack ItemStack to insert.
* @param simulate If true, the insertion is only simulated
* @param predicate See interface notes about predicates. Passing null specifies default matching.
* @return The remaining ItemStack that was not inserted. If the entire stack was accepted, returns
* ItemStack.EMPTY instead.
*/
@Nonnull
ItemStack insertItem (@Nonnull ItemStack stack, boolean simulate, Predicate<ItemStack> predicate);
@Nonnull
default ItemStack insertItem (@Nonnull ItemStack stack, boolean simulate) {
return insertItem(stack, simulate, null);
}
/**
* Tries to extract the given ItemStack from the inventory. The returned value will be a matching ItemStack
* with a stack size equal to or less than amount, or the empty ItemStack if the item could not be found at all.
* The returned stack size may exceed the ItemStack's getMaxStackSize() value.
* @param stack The item to extract. The stack size is ignored.
* @param amount Amount to extract (may be greater than the stacks max limit)
* @param simulate If true, the extraction is only simulated
* @param predicate See interface notes about predicates. Passing null specifies default matching.
* @return ItemStack extracted from the inventory, or ItemStack.EMPTY if nothing could be extracted.
*/
@Nonnull
ItemStack extractItem (@Nonnull ItemStack stack, int amount, boolean simulate, Predicate<ItemStack> predicate);
@Nonnull
default ItemStack extractItem (@Nonnull ItemStack stack, int amount, boolean simulate) {
return extractItem(stack, amount, simulate, null);
}
/**
* Gets the number of items matching the given ItemStack stored by the inventory.
* @param stack ItemStack to query.
* @param predicate See interface notes about predicates. Passing null specifies default matching.
* @return The number of stored matching items. A value of Integer.MAX_VALUE may indicate an infinite item source.
*/
default int getStoredItemCount (@Nonnull ItemStack stack, Predicate<ItemStack> predicate) {
ItemStack amount = extractItem(stack, Integer.MAX_VALUE, true, predicate);
return amount.getCount();
}
default int getStoredItemCount (@Nonnull ItemStack stack) {
return getStoredItemCount(stack, null);
}
/**
* Gets the number items matching the given ItemStack that additionally still be stored by the inventory.
* Remaining capacity may include space that is internally empty or unassigned to any given item.
*
* @param stack ItemStack to query.
* @param predicate See interface notes about predicates. Passing null specifies default matching.
* @return The available remaining space for matching items.
*/
default int getRemainingItemCapacity (@Nonnull ItemStack stack, Predicate<ItemStack> predicate) {
stack = stack.copy();
stack.setCount(Integer.MAX_VALUE);
ItemStack remainder = insertItem(stack, true, predicate);
return Integer.MAX_VALUE - remainder.getCount();
}
default int getRemainingItemCapacity (@Nonnull ItemStack stack) {
return getRemainingItemCapacity(stack, null);
}
/**
* Gets the total inventory capacity for items matching the given ItemStack.
* Total capacity may include space that is internally empty or unassigned to any given item.
*
* @param stack ItemStack to query.
* @param predicate See interface notes about predicates. Passing null specifies default matching.
* @return The total capacity for matching items.
*/
default int getItemCapacity (@Nonnull ItemStack stack, Predicate<ItemStack> predicate) {
long capacity = getStoredItemCount(stack, predicate) + getRemainingItemCapacity(stack, predicate);
if (capacity > Integer.MAX_VALUE)
return Integer.MAX_VALUE;
return (int)capacity;
}
default int getItemCapacity (@Nonnull ItemStack stack) {
return getItemCapacity(stack, null);
}
/**
* An item record representing an item and the amount stored.
*
* The ItemStack held by itemPrototype always reports a stack size of 1.
* IT IS IMPORTANT THAT YOU NEVER MODIFY itemPrototype.
*/
class ItemRecord
{
@Nonnull
public final ItemStack itemPrototype;
public final int count;
public ItemRecord (@Nonnull ItemStack itemPrototype, int count) {
this.itemPrototype = itemPrototype;
this.count = count;
}
}
/**
* A variant of the standard Predicate interface that when passed to IItemRepository functions, will ask the
* internal default predicate to be tested in addition to the custom predicate. An IItemRepository function
* may choose to enforce its own predicate regardless.
*/
interface DefaultPredicate<T> extends Predicate<T> { }
}
+27 -4
View File
@@ -25,8 +25,11 @@ import java.util.EnumMap;
import java.util.List;
import java.util.Random;
import appeng.client.gui.AEBaseGui;
import appeng.container.interfaces.IJEIGhostIngredients;
import appeng.helpers.HighlighterHandler;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.entity.player.EntityPlayer;
@@ -36,10 +39,7 @@ import net.minecraft.util.EnumHand;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.client.event.MouseEvent;
import net.minecraftforge.client.event.RenderLivingEvent;
import net.minecraftforge.client.event.RenderWorldLastEvent;
import net.minecraftforge.client.event.TextureStitchEvent;
import net.minecraftforge.client.event.*;
import net.minecraftforge.client.model.ModelLoaderRegistry;
import net.minecraftforge.common.ForgeModContainer;
import net.minecraftforge.common.MinecraftForge;
@@ -75,6 +75,7 @@ import appeng.hooks.TickHandler;
import appeng.hooks.TickHandler.PlayerColor;
import appeng.server.ServerHelper;
import appeng.util.Platform;
import org.lwjgl.input.Mouse;
public class ClientHelper extends ServerHelper
@@ -315,6 +316,28 @@ public class ClientHelper extends ServerHelper
Minecraft.getMinecraft().effectRenderer.addEffect( fx );
}
@SubscribeEvent
public void MouseClickEvent( final GuiScreenEvent.MouseInputEvent.Pre me )
{
final Minecraft mc = Minecraft.getMinecraft();
if( mc.currentScreen instanceof IJEIGhostIngredients )
{
AEBaseGui gui = ( (AEBaseGui) mc.currentScreen );
Object ingredient = gui.getBookmarkedIngredient();
if( ingredient != null )
{
if( GuiScreen.isShiftKeyDown() )
{
me.setCanceled( true );
}
else if( Mouse.isButtonDown( 0 ) )
{
me.setCanceled( true );
}
}
}
}
@SubscribeEvent
public void wheelEvent( final MouseEvent me )
{
+141 -23
View File
@@ -19,6 +19,7 @@
package appeng.client.gui;
import java.awt.*;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.ParseException;
@@ -31,13 +32,16 @@ import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import appeng.tile.inventory.AppEngInternalInventory;
import appeng.container.slot.*;
import com.google.common.base.Joiner;
import com.google.common.base.Stopwatch;
import com.google.common.collect.Lists;
import mezz.jei.api.gui.IGhostIngredientHandler;
import net.minecraft.client.gui.Gui;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.FluidUtil;
import net.minecraftforge.fml.common.Optional;
import net.minecraftforge.items.IItemHandler;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
@@ -71,17 +75,7 @@ import appeng.client.me.SlotDisconnected;
import appeng.client.me.SlotME;
import appeng.client.render.StackSizeRenderer;
import appeng.container.AEBaseContainer;
import appeng.container.slot.AppEngCraftingSlot;
import appeng.container.slot.AppEngSlot;
import appeng.container.slot.AppEngSlot.hasCalculatedValidness;
import appeng.container.slot.IOptionalSlot;
import appeng.container.slot.SlotCraftingTerm;
import appeng.container.slot.SlotDisabled;
import appeng.container.slot.SlotFake;
import appeng.container.slot.SlotInaccessible;
import appeng.container.slot.SlotOutput;
import appeng.container.slot.SlotPatternTerm;
import appeng.container.slot.SlotRestrictedInput;
import appeng.core.AELog;
import appeng.core.AppEng;
import appeng.core.sync.network.NetworkHandler;
@@ -92,6 +86,9 @@ import appeng.fluids.container.slots.IMEFluidSlot;
import appeng.helpers.InventoryAction;
import yalter.mousetweaks.api.IMTModGuiContainer2;
import static appeng.integration.modules.jei.JEIPlugin.aeGuiHandler;
import static appeng.integration.modules.jei.JEIPlugin.runtime;
@Optional.Interface( iface = "yalter.mousetweaks.api.IMTModGuiContainer2", modid = "mousetweaks" )
public abstract class AEBaseGui extends GuiContainer implements IMTModGuiContainer2
@@ -106,6 +103,28 @@ public abstract class AEBaseGui extends GuiContainer implements IMTModGuiContain
private Stopwatch dbl_clickTimer = Stopwatch.createStarted();
private ItemStack dbl_whichItem = ItemStack.EMPTY;
private Slot bl_clicked;
private Stopwatch lastClicked = Stopwatch.createStarted();
private List<IGhostIngredientHandler.Target<Object>> hoveredIngredientTargets = new ArrayList<>();
private Object bookmarkedIngredient;
private boolean isDraggingJeiGhostItem;
public void setJeiGhostItem( boolean jeiGhostItem )
{
isJeiGhostItem = jeiGhostItem;
}
private boolean isJeiGhostItem;
public Object getBookmarkedIngredient()
{
return bookmarkedIngredient;
}
public List<GuiCustomSlot> getGuiSlots()
{
return guiSlots;
}
protected final List<GuiCustomSlot> guiSlots = new ArrayList<>();
public AEBaseGui( final Container container )
@@ -188,6 +207,65 @@ public abstract class AEBaseGui extends GuiContainer implements IMTModGuiContain
this.drawTooltip( (ITooltip) c, mouseX, mouseY );
}
}
GlStateManager.enableDepth();
bookmarkedJEIghostItem(mouseX,mouseY);
GlStateManager.disableDepth();
}
void bookmarkedJEIghostItem(final int mouseX, final int mouseY) {
if (!isJeiGhostItem)
{
bookmarkedIngredient = runtime.getBookmarkOverlay().getIngredientUnderMouse();
}
if( bookmarkedIngredient != null )
{
hoveredIngredientTargets = aeGuiHandler.getTargets( this, bookmarkedIngredient, false );
ItemStack dragItem = ItemStack.EMPTY;
if( hoveredIngredientTargets.size() > 0 )
{
if( isShiftKeyDown() && Mouse.isButtonDown( 0 ) && this.lastClicked.elapsed( TimeUnit.MILLISECONDS ) > 200 )
{
this.lastClicked = Stopwatch.createStarted();
aeGuiHandler.getTargets( this, bookmarkedIngredient, true );
}
else if( Mouse.isButtonDown( 0 ) && this.lastClicked.elapsed( TimeUnit.MILLISECONDS ) > 200 )
{
this.lastClicked = Stopwatch.createStarted();
if( bookmarkedIngredient instanceof ItemStack )
{
dragItem = ( (ItemStack) bookmarkedIngredient );
}
else if( bookmarkedIngredient instanceof FluidStack )
{
dragItem = FluidUtil.getFilledBucket( ( (FluidStack) bookmarkedIngredient ) );
}
mc.player.inventory.setItemStack( dragItem.copy() );
this.isJeiGhostItem = true;
}
drawTargets( mouseX, mouseY );
}
}
}
private void drawTargets(int mouseX, int mouseY) {
GlStateManager.disableLighting();
for( IGhostIngredientHandler.Target target : hoveredIngredientTargets )
{
Rectangle area = target.getArea();
Color color;
if( area.contains( mouseX, mouseY ) )
{
color = new Color( 76, 201, 25, 128 );
}
else
{
color = new Color( 19, 201, 10, 64 );
}
Gui.drawRect( area.x, area.y, area.x + area.width, area.y + area.height, color.getRGB() );
}
GlStateManager.color( 1f, 1f, 1f, 1f );
GlStateManager.enableDepth();
}
protected void drawGuiSlot( GuiCustomSlot slot, int mouseX, int mouseY, float partialTicks )
@@ -320,7 +398,6 @@ public abstract class AEBaseGui extends GuiContainer implements IMTModGuiContain
{
slot.drawBackground( ox, oy );
}
}
@Override
@@ -429,18 +506,56 @@ public abstract class AEBaseGui extends GuiContainer implements IMTModGuiContain
{
final EntityPlayer player = Minecraft.getMinecraft().player;
if( slot instanceof SlotFake )
if( this.isJeiGhostItem && isDraggingJeiGhostItem)
{
final InventoryAction action = mouseButton == 1 ? InventoryAction.SPLIT_OR_PLACE_SINGLE : InventoryAction.PICKUP_OR_SET_DOWN;
for( IGhostIngredientHandler.Target target : hoveredIngredientTargets )
{
Rectangle area = target.getArea();
final int x = Mouse.getEventX() * this.width / this.mc.displayWidth;
final int y = this.height - Mouse.getEventY() * this.height / this.mc.displayHeight - 1;
if( area.contains( x, y ) )
{
target.accept( bookmarkedIngredient );
break;
}
}
this.isJeiGhostItem = false;
this.isDraggingJeiGhostItem = false;
ItemStack dragItem = ItemStack.EMPTY;
if( runtime.getBookmarkOverlay().getIngredientUnderMouse() != null )
{
bookmarkedJEIghostItem( Mouse.getX(), this.mc.displayHeight - Mouse.getY() );
if( bookmarkedIngredient instanceof ItemStack )
{
dragItem = ( (ItemStack) bookmarkedIngredient );
}
else if( bookmarkedIngredient instanceof FluidStack )
{
dragItem = FluidUtil.getFilledBucket( ( (FluidStack) bookmarkedIngredient ) );
}
mc.player.inventory.setItemStack( dragItem.copy() );
this.isJeiGhostItem = true;
}
else
{
mc.player.inventory.setItemStack( dragItem );
}
}
else if( slot instanceof SlotFake )
{
final InventoryAction action;
action = mouseButton == 1 ? InventoryAction.SPLIT_OR_PLACE_SINGLE : InventoryAction.PICKUP_OR_SET_DOWN;
if( this.drag_click.size() > 1 )
{
return;
}
final PacketInventoryAction p = new PacketInventoryAction( action, slotIdx, 0 );
PacketInventoryAction p = new PacketInventoryAction( action, slotIdx, 0 );
NetworkHandler.instance().sendToServer( p );
return;
}
@@ -560,14 +675,13 @@ public abstract class AEBaseGui extends GuiContainer implements IMTModGuiContain
InventoryAction action = null;
IAEItemStack stack = null;
switch( clickType )
switch ( clickType )
{
case PICKUP: // pickup / set-down.
action = ( mouseButton == 1 ) ? InventoryAction.SPLIT_OR_PLACE_SINGLE : InventoryAction.PICKUP_OR_SET_DOWN;
stack = ( (SlotME) slot ).getAEStack();
if( stack != null && action == InventoryAction.PICKUP_OR_SET_DOWN && stack.getStackSize() == 0 && player.inventory.getItemStack()
.isEmpty() )
if( stack != null && action == InventoryAction.PICKUP_OR_SET_DOWN && stack.getStackSize() == 0 && player.inventory.getItemStack().isEmpty() )
{
action = InventoryAction.AUTO_CRAFT;
}
@@ -634,9 +748,7 @@ public abstract class AEBaseGui extends GuiContainer implements IMTModGuiContain
final List<Slot> slots = this.getInventorySlots();
for( final Slot inventorySlot : slots )
{
if( inventorySlot != null && inventorySlot.canTakeStack(
this.mc.player ) && inventorySlot.getHasStack() && inventorySlot.isSameInventory( slot ) && Container.canAddItemToSlot(
inventorySlot, this.dbl_whichItem, true ) )
if( inventorySlot != null && inventorySlot.canTakeStack( this.mc.player ) && inventorySlot.getHasStack() && inventorySlot.isSameInventory( slot ) && Container.canAddItemToSlot( inventorySlot, this.dbl_whichItem, true ) )
{
this.handleMouseClick( inventorySlot, inventorySlot.slotNumber, 0, ClickType.QUICK_MOVE );
}
@@ -647,6 +759,11 @@ public abstract class AEBaseGui extends GuiContainer implements IMTModGuiContain
this.disableShiftClick = false;
}
if (clickType == ClickType.PICKUP && isJeiGhostItem && !isDraggingJeiGhostItem) {
this.isDraggingJeiGhostItem = true;
return;
}
super.handleMouseClick( slot, slotIdx, mouseButton, clickType );
}
@@ -1074,4 +1191,5 @@ public abstract class AEBaseGui extends GuiContainer implements IMTModGuiContain
{
return false;
}
}
@@ -2,26 +2,23 @@ package appeng.client.gui;
import javax.annotation.Nullable;
import appeng.api.storage.data.IAEItemStack;
import appeng.client.gui.implementations.GuiCraftAmount;
import appeng.client.gui.implementations.GuiCraftConfirm;
import appeng.client.gui.implementations.GuiCraftingCPU;
import appeng.client.gui.widgets.GuiCustomSlot;
import appeng.container.implementations.ContainerCraftAmount;
import appeng.client.gui.implementations.*;
import appeng.container.interfaces.IJEIGhostIngredients;
import appeng.container.slot.SlotFake;
import appeng.fluids.client.gui.widgets.GuiFluidSlot;
import mezz.jei.api.gui.IAdvancedGuiHandler;
import net.minecraft.client.renderer.RenderItem;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
import mezz.jei.api.gui.IGhostIngredientHandler;
import net.minecraft.client.gui.GuiScreen;
import org.lwjgl.input.Mouse;
import java.awt.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class AEGuiHandler implements IAdvancedGuiHandler<AEBaseGui>
public class AEGuiHandler implements IAdvancedGuiHandler<AEBaseGui>, IGhostIngredientHandler<AEBaseGui>
{
@Override
public Class<AEBaseGui> getGuiContainerClass()
{
@@ -39,8 +36,8 @@ public class AEGuiHandler implements IAdvancedGuiHandler<AEBaseGui>
@Override
public Object getIngredientUnderMouse( AEBaseGui guiContainer, int mouseX, int mouseY )
{
List<IAEItemStack> visual = new ArrayList<>();
int guiSlotIdx = 0;
List<IAEItemStack> visual;
int guiSlotIdx;
Object result = null;
if( guiContainer instanceof GuiCraftConfirm )
{
@@ -94,4 +91,54 @@ public class AEGuiHandler implements IAdvancedGuiHandler<AEBaseGui>
if( guiSloty > ( rows - 1 ) || mouseY < guitop + yo ) return -1;
return ( guiSloty * 3 ) + guiSlotx + ( currentScroll * 3 );
}
@Override
public <I> List<Target<I>> getTargets( AEBaseGui gui, I ingredient, boolean doStart )
{
ArrayList<Target<I>> targets = new ArrayList<>();
if( gui instanceof IJEIGhostIngredients )
{
IJEIGhostIngredients g = (IJEIGhostIngredients) gui;
List<Target<?>> phantomTargets = g.getPhantomTargets( ingredient );
targets.addAll( (List<Target<I>>) (Object) phantomTargets );
}
if( doStart && GuiScreen.isShiftKeyDown() && Mouse.isButtonDown( 0 ) )
{
if( gui instanceof GuiUpgradeable || gui instanceof GuiPatternTerm )
{
IJEIGhostIngredients ghostGui = ( (IJEIGhostIngredients) gui );
for( Target<I> target : targets )
{
if( ghostGui.getFakeSlotTargetMap().get( target ) instanceof SlotFake )
{
if( ( (SlotFake) ghostGui.getFakeSlotTargetMap().get( target ) ).getStack().isEmpty() )
{
target.accept( ingredient );
break;
}
}
else if( ghostGui.getFakeSlotTargetMap().get( target ) instanceof GuiFluidSlot )
{
if( ( (GuiFluidSlot) ghostGui.getFakeSlotTargetMap().get( target ) ).getFluidStack() == null )
{
target.accept( ingredient );
break;
}
}
}
}
}
return targets;
}
@Override
public void onComplete(){
}
@Override
public boolean shouldHighlightTargets()
{
return true;
}
}
@@ -49,6 +49,7 @@ import appeng.util.Platform;
import net.minecraft.nbt.NBTUtil;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.TextComponentString;
import org.lwjgl.input.Mouse;
import static appeng.client.render.BlockPosHighlighter.hilightBlock;
@@ -68,6 +69,7 @@ public class GuiInterfaceTerminal extends AEBaseGui
private final HashMap<GuiButton,ClientDCInternalInv> guiButtonHashMap = new HashMap<>();
private final ArrayList<String> names = new ArrayList<>();
private final ArrayList<Object> lines = new ArrayList<>();
private final Set<Object> matchedStacks = new HashSet<>();
private final Map<String, Set<Object>> cachedSearches = new WeakHashMap<>();
@@ -153,6 +155,8 @@ public class GuiInterfaceTerminal extends AEBaseGui
for( int z = 0; z < inv.getInventory().getSlots(); z++ )
{
this.inventorySlots.inventorySlots.add( new SlotDisconnected( inv, z, z * 18 + 22, 1 + offset ) );
if (this.matchedStacks.contains(inv.getInventory().getStackInSlot(z)))
drawRect( z * 18 + 22, 1 + offset, z * 18 + 22 + 16, 1 + offset + 16, 0x2A00FF00 );
}
GuiButton guiButton = new GuiImgButton(guiLeft + 4, guiTop + offset + 1, Settings.ACTIONS, ActionItems.HIGHLIGHT_INTERFACE);
@@ -179,8 +183,8 @@ public class GuiInterfaceTerminal extends AEBaseGui
offset += 18;
}
if( searchFieldInputs.isMouseIn( mouseX, mouseY ) ) drawTooltip( mouseX - guiLeft - offsetX, mouseY - guiTop, "Inputs OR names" );
else if( searchFieldOutputs.isMouseIn( mouseX, mouseY ) ) drawTooltip( mouseX - guiLeft - offsetX, mouseY - guiTop, "Outputs OR names" );
if( searchFieldInputs.isMouseIn( mouseX , mouseY ) ) drawTooltip( Mouse.getEventX() * this.width / this.mc.displayWidth - offsetX, mouseY - guiTop, "Inputs OR names" );
else if( searchFieldOutputs.isMouseIn( mouseX, mouseY ) ) drawTooltip( Mouse.getEventX() * this.width / this.mc.displayWidth - offsetX, mouseY - guiTop, "Outputs OR names" );
}
@@ -355,6 +359,7 @@ public class GuiInterfaceTerminal extends AEBaseGui
{
this.byName.clear();
this.buttonList.clear();
this.matchedStacks.clear();
final String searchFieldInputs = this.searchFieldInputs.getText().toLowerCase();
final String searchFieldOutputs = this.searchFieldOutputs.getText().toLowerCase();
@@ -380,19 +385,27 @@ public class GuiInterfaceTerminal extends AEBaseGui
{
for( final ItemStack itemStack : entry.getInventory() )
{
if( !searchFieldInputs.isEmpty() && !searchFieldOutputs.isEmpty() )
found = ( this.itemStackMatchesSearchTerm( itemStack, searchFieldInputs, 0 ) || this.itemStackMatchesSearchTerm( itemStack, searchFieldOutputs, 1 ) );
else if( !searchFieldInputs.isEmpty() )
found = ( this.itemStackMatchesSearchTerm( itemStack, searchFieldInputs, 0 ) );
else if( !searchFieldOutputs.isEmpty() )
found = ( this.itemStackMatchesSearchTerm( itemStack, searchFieldOutputs, 1 ) );
if( !searchFieldInputs.isEmpty() && !searchFieldOutputs.isEmpty() ) {
if (this.itemStackMatchesSearchTerm(itemStack, searchFieldInputs, 0) || this.itemStackMatchesSearchTerm(itemStack, searchFieldOutputs, 1)) {
found = true;
matchedStacks.add(itemStack);
}
}
else if( !searchFieldInputs.isEmpty() ) {
if (this.itemStackMatchesSearchTerm(itemStack, searchFieldInputs, 0)) {
found = true;
matchedStacks.add(itemStack);
}
}
else if( !searchFieldOutputs.isEmpty() ) {
if (this.itemStackMatchesSearchTerm(itemStack, searchFieldOutputs, 1)) {
found = true;
matchedStacks.add(itemStack);
}
}
// If only Interfaces with empty slots should be shown, check that here
if(itemStack.isEmpty())
interfaceHasFreeSlots = true;
if( found )
{
break;
}
}
}
// if found, filter skipped or machine name matching the search term, add it
@@ -19,11 +19,21 @@
package appeng.client.gui.implementations;
import java.awt.*;
import java.io.IOException;
import java.util.*;
import java.util.List;
import appeng.container.interfaces.IJEIGhostIngredients;
import appeng.container.slot.SlotFake;
import appeng.core.sync.packets.PacketInventoryAction;
import appeng.helpers.InventoryAction;
import appeng.util.item.AEItemStack;
import mezz.jei.api.gui.IGhostIngredientHandler.Target;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
import appeng.api.config.ActionItems;
@@ -40,7 +50,7 @@ import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.PacketValueConfig;
public class GuiPatternTerm extends GuiMEMonitorable
public class GuiPatternTerm extends GuiMEMonitorable implements IJEIGhostIngredients
{
private static final String BACKGROUND_CRAFTING_MODE = "guis/pattern.png";
@@ -67,6 +77,7 @@ public class GuiPatternTerm extends GuiMEMonitorable
private GuiImgButton divThreeBtn;
private GuiImgButton minusOneBtn;
private GuiImgButton maxCountBtn;
public Map<Target<?>,Object> mapTargetSlot = new HashMap<>();
public GuiPatternTerm( final InventoryPlayer inventoryPlayer, final ITerminalHost te )
{
@@ -274,4 +285,52 @@ public class GuiPatternTerm extends GuiMEMonitorable
s.yPos = s.getY() + this.ySize - 78 - offsetPlayerSide;
}
@Override
public List<Target<?>> getPhantomTargets(Object ingredient) {
if (!(ingredient instanceof ItemStack )) {
return Collections.emptyList();
}
List<Target<?>> targets = new ArrayList<>();
for( Slot slot : this.inventorySlots.inventorySlots )
{
if( slot instanceof SlotFake )
{
ItemStack itemStack = (ItemStack) ingredient;
Target<Object> target = new Target<Object>()
{
@Override
public Rectangle getArea()
{
return new Rectangle( getGuiLeft() + slot.xPos, getGuiTop() + slot.yPos, 16, 16 );
}
@Override
public void accept( Object ingredient )
{
final PacketInventoryAction p;
try
{
p = new PacketInventoryAction( InventoryAction.PLACE_JEI_GHOST_ITEM, (SlotFake) slot, AEItemStack.fromItemStack( itemStack ) );
NetworkHandler.instance().sendToServer( p );
}
catch( IOException e )
{
e.printStackTrace();
}
}
};
targets.add( target );
mapTargetSlot.putIfAbsent( target, slot );
}
}
return targets;
}
@Override
public Map<Target<?>, Object> getFakeSlotTargetMap()
{
return mapTargetSlot;
}
}
@@ -19,8 +19,24 @@
package appeng.client.gui.implementations;
import java.awt.*;
import java.io.IOException;
import java.util.*;
import java.util.List;
import appeng.client.gui.widgets.GuiCustomSlot;
import appeng.container.interfaces.IJEIGhostIngredients;
import appeng.container.slot.IJEITargetSlot;
import appeng.container.slot.SlotFake;
import appeng.core.sync.packets.PacketInventoryAction;
import appeng.fluids.client.gui.widgets.GuiFluidSlot;
import appeng.fluids.util.AEFluidStack;
import appeng.helpers.InventoryAction;
import appeng.util.item.AEItemStack;
import mezz.jei.api.gui.IGhostIngredientHandler.Target;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fluids.*;
import org.lwjgl.input.Mouse;
import net.minecraft.client.gui.GuiButton;
@@ -43,9 +59,9 @@ import appeng.parts.automation.PartExportBus;
import appeng.parts.automation.PartImportBus;
public class GuiUpgradeable extends AEBaseGui
public class GuiUpgradeable extends AEBaseGui implements IJEIGhostIngredients
{
private final Map<Target<?>,Object> mapTargetSlot = new HashMap<>();
protected final ContainerUpgradeable cvb;
protected final IUpgradeableHost bc;
@@ -200,4 +216,108 @@ public class GuiUpgradeable extends AEBaseGui
NetworkHandler.instance().sendToServer( new PacketConfigButton( this.schedulingMode.getSetting(), backwards ) );
}
}
@Override
public List<Target<?>> getPhantomTargets(Object ingredient)
{
mapTargetSlot.clear();
FluidStack fluidStack = null;
ItemStack itemStack = ItemStack.EMPTY;
if( ingredient instanceof ItemStack )
{
itemStack = (ItemStack) ingredient;
fluidStack = FluidUtil.getFluidContained( itemStack );
}
else if( ingredient instanceof FluidStack )
{
fluidStack = (FluidStack) ingredient;
}
if( !( ingredient instanceof ItemStack ) && !( ingredient instanceof FluidStack ) )
return Collections.emptyList();
List<Target<?>> targets = new ArrayList<>();
List<IJEITargetSlot> slots = new ArrayList<>();
if( this.inventorySlots.inventorySlots.size() > 0 )
{
for( Slot slot : this.inventorySlots.inventorySlots )
{
if( slot instanceof SlotFake && ( !itemStack.isEmpty() || this instanceof GuiCellWorkbench && fluidStack != null ) )
{
slots.add( (IJEITargetSlot) slot );
}
}
}
if( this.getGuiSlots().size() > 0 )
{
for( GuiCustomSlot slot : this.getGuiSlots() )
{
if( slot instanceof GuiFluidSlot && fluidStack != null )
{
slots.add( (IJEITargetSlot) slot );
}
}
}
for( Object slot : slots )
{
ItemStack finalItemStack = itemStack;
FluidStack finalFluidStack = fluidStack;
Target<Object> targetItem = new Target<Object>()
{
@Override
public Rectangle getArea()
{
if( slot instanceof SlotFake )
return new Rectangle( getGuiLeft() + ( (SlotFake) slot ).xPos, getGuiTop() + ( (SlotFake) slot ).yPos, 16, 16 );
else
{
return new Rectangle( getGuiLeft() + ( (GuiFluidSlot) slot ).xPos(), getGuiTop() + ( (GuiFluidSlot) slot ).yPos(), 16, 16 );
}
}
@Override
public void accept( Object ingredient )
{
PacketInventoryAction p = null;
try
{
if( slot instanceof SlotFake )
{
if( finalItemStack.isEmpty() && finalFluidStack != null )
{
p = new PacketInventoryAction( InventoryAction.PLACE_JEI_GHOST_ITEM, (IJEITargetSlot) slot, AEItemStack.fromItemStack( FluidUtil.getFilledBucket( finalFluidStack ) ) );
}
else if( !finalItemStack.isEmpty() )
{
p = new PacketInventoryAction( InventoryAction.PLACE_JEI_GHOST_ITEM, (IJEITargetSlot) slot, AEItemStack.fromItemStack( finalItemStack ) );
}
}
else
{
if( finalFluidStack == null ) return;
p = new PacketInventoryAction( InventoryAction.PLACE_JEI_GHOST_ITEM, (IJEITargetSlot) slot, AEItemStack.fromItemStack( AEFluidStack.fromFluidStack( finalFluidStack ).asItemStackRepresentation() ) );
}
NetworkHandler.instance().sendToServer( p );
}
catch( IOException e )
{
e.printStackTrace();
}
}
};
targets.add( targetItem );
mapTargetSlot.putIfAbsent( targetItem, slot );
}
return targets;
}
@Override
public Map<Target<?>, Object> getFakeSlotTargetMap()
{
return mapTargetSlot;
}
}
@@ -0,0 +1,18 @@
package appeng.container.interfaces;
import mezz.jei.api.gui.IGhostIngredientHandler.Target;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public interface IJEIGhostIngredients
{
List<Target<?>> getPhantomTargets( Object ingredient );
default Map<Target<?>, Object> getFakeSlotTargetMap(){
return new HashMap<>();
}
}
@@ -0,0 +1,4 @@
package appeng.container.slot;
public interface IJEITargetSlot {
}
@@ -24,7 +24,7 @@ import net.minecraft.item.ItemStack;
import net.minecraftforge.items.IItemHandler;
public class SlotFake extends AppEngSlot
public class SlotFake extends AppEngSlot implements IJEITargetSlot
{
public SlotFake( final IItemHandler inv, final int idx, final int x, final int y )
@@ -21,6 +21,14 @@ package appeng.core.sync.packets;
import java.io.IOException;
import appeng.api.storage.data.IAEFluidStack;
import appeng.container.slot.IJEITargetSlot;
import appeng.container.slot.SlotFake;
import appeng.core.AELog;
import appeng.core.sync.network.NetworkHandler;
import appeng.fluids.client.gui.widgets.GuiFluidSlot;
import appeng.fluids.container.ContainerFluidConfigurable;
import appeng.fluids.util.AEFluidStack;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
@@ -40,6 +48,7 @@ import appeng.core.sync.network.INetworkInfo;
import appeng.helpers.InventoryAction;
import appeng.util.Platform;
import appeng.util.item.AEItemStack;
import net.minecraftforge.fluids.FluidStack;
public class PacketInventoryAction extends AppEngPacket
@@ -57,6 +66,7 @@ public class PacketInventoryAction extends AppEngPacket
this.slot = stream.readInt();
this.id = stream.readLong();
final boolean hasItem = stream.readBoolean();
if( hasItem )
{
this.slotItem = AEItemStack.fromPacket( stream );
@@ -70,7 +80,6 @@ public class PacketInventoryAction extends AppEngPacket
// api
public PacketInventoryAction( final InventoryAction action, final int slot, final IAEItemStack slotItem ) throws IOException
{
if( Platform.isClient() )
{
throw new IllegalStateException( "invalid packet, client cannot post inv actions with stacks." );
@@ -101,6 +110,36 @@ public class PacketInventoryAction extends AppEngPacket
this.configureWrite( data );
}
public PacketInventoryAction(final InventoryAction action, final IJEITargetSlot slot, final IAEItemStack slotItem ) throws IOException
{
this.action = action;
if (slot instanceof SlotFake)
this.slot = ((SlotFake) slot).slotNumber;
else this.slot = ((GuiFluidSlot) slot).getId();
this.id = 0;
this.slotItem = slotItem;
final ByteBuf data = Unpooled.buffer();
data.writeInt( this.getPacketID() );
data.writeInt( action.ordinal() );
data.writeInt( this.slot );
data.writeLong( this.id );
if( slotItem == null )
{
data.writeBoolean( false );
}
else
{
data.writeBoolean( true );
slotItem.writeToPacket( data );
}
this.configureWrite( data );
}
// api
public PacketInventoryAction( final InventoryAction action, final int slot, final long id )
{
@@ -150,6 +189,46 @@ public class PacketInventoryAction extends AppEngPacket
}
}
}
else if( this.action == InventoryAction.PLACE_JEI_GHOST_ITEM )
{
if( sender.openContainer.inventorySlots.get( this.slot ) instanceof SlotFake )
{
if( this.slotItem != null )
{
sender.openContainer.inventorySlots.get( this.slot ).putStack( this.slotItem.createItemStack() );
if( sender.openContainer.inventorySlots.get( this.slot ).getStack().isEmpty() )
{
IAEFluidStack aefs = AEFluidStack.fromNBT( this.slotItem.getDefinition().getTagCompound() );
if( aefs != null )
{
FluidStack fluid = aefs.getFluidStack();
sender.openContainer.inventorySlots.get( this.slot ).putStack( AEFluidStack.fromFluidStack( fluid ).asItemStackRepresentation() );
}
}
}
else sender.openContainer.inventorySlots.get( this.slot ).putStack( ItemStack.EMPTY );
try
{
NetworkHandler.instance().sendTo( new PacketInventoryAction( InventoryAction.UPDATE_HAND, 0, AEItemStack.fromItemStack( ItemStack.EMPTY ) ), sender );
}
catch( final IOException e )
{
AELog.debug( e );
}
}
if( sender.openContainer instanceof ContainerFluidConfigurable )
{
if( this.slotItem != null )
{
IAEFluidStack aefs = AEFluidStack.fromNBT( this.slotItem.getDefinition().getTagCompound() );
if( aefs != null )
{
( (ContainerFluidConfigurable) sender.openContainer ).getFluidConfigInventory().setFluidInSlot( this.slot, aefs );
}
}
}
}
else
{
baseContainer.doAction( sender, this.action, this.slot, this.id );
@@ -303,7 +303,7 @@ public class PacketJEIRecipe extends AppEngPacket
{
for( ItemStack option : this.recipe[slot] )
{
if( is.isItemEqual( option ) )
if( ItemStack.areItemStacksEqual( is, option ) )
{
return is;
}
@@ -4,6 +4,7 @@ package appeng.fluids.client.gui.widgets;
import java.util.Collections;
import appeng.container.slot.IJEITargetSlot;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
@@ -23,7 +24,7 @@ import appeng.fluids.util.AEFluidStack;
import appeng.fluids.util.IAEFluidTank;
public class GuiFluidSlot extends GuiCustomSlot
public class GuiFluidSlot extends GuiCustomSlot implements IJEITargetSlot
{
private final IAEFluidTank fluids;
private final int slot;
@@ -149,6 +149,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
private int isWorking = -1;
private final Accessor accessor = new Accessor();
private GTCEInventoryAdaptor GTad;
EnumSet<EnumFacing> visitedFaces = EnumSet.noneOf( EnumFacing.class );
public DualityInterface( final AENetworkProxy networkProxy, final IInterfaceHost ih )
{
@@ -939,8 +940,12 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
final World w = tile.getWorld();
final EnumSet<EnumFacing> possibleDirections = this.iHost.getTargets();
for( final EnumFacing s : possibleDirections )
{
if (visitedFaces.contains( s ))
continue;
final TileEntity te = w.getTileEntity( tile.getPos().offset( s ) );
if( te instanceof IInterfaceHost )
{
@@ -964,6 +969,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
{
if( cm.pushPattern( patternDetails, table, s.getOpposite() ) )
{
visitedFaces.add( s );
return true;
}
continue;
@@ -1004,10 +1010,12 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
}
}
this.pushItemsOut( possibleDirections );
visitedFaces.add( s );
return true;
}
}
}
visitedFaces.clear();
return false;
}
@@ -43,5 +43,6 @@ public enum InventoryAction
ROLL_UP,
ROLL_DOWN,
AUTO_CRAFT,
PLACE_SINGLE
PLACE_SINGLE,
PLACE_JEI_GHOST_ITEM
}
@@ -19,6 +19,8 @@
package appeng.integration.modules.jei;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@@ -27,14 +29,11 @@ import appeng.client.gui.AEGuiHandler;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import mezz.jei.api.*;
import mezz.jei.config.Constants;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import mezz.jei.api.IJeiRuntime;
import mezz.jei.api.IModPlugin;
import mezz.jei.api.IModRegistry;
import mezz.jei.api.ISubtypeRegistry;
import mezz.jei.api.recipe.IRecipeCategoryRegistration;
import mezz.jei.api.recipe.VanillaRecipeCategoryUid;
@@ -57,6 +56,9 @@ import appeng.items.parts.ItemFacade;
@mezz.jei.api.JEIPlugin
public class JEIPlugin implements IModPlugin
{
public static IJeiRuntime runtime;
public static AEGuiHandler aeGuiHandler;
@Override
public void registerItemSubtypes( ISubtypeRegistry subtypeRegistry )
{
@@ -95,8 +97,9 @@ public class JEIPlugin implements IModPlugin
.addRecipeTransferHandler( new RecipeTransferHandler<>( ContainerPatternTerm.class ),
Constants.UNIVERSAL_RECIPE_TRANSFER_UID );
AEGuiHandler aeGuiHandler = new AEGuiHandler();
aeGuiHandler = new AEGuiHandler();
registry.addAdvancedGuiHandlers(aeGuiHandler);
registry.addGhostIngredientHandler( aeGuiHandler.getGuiContainerClass(), aeGuiHandler);
}
private void registerDescriptions( IDefinitions definitions, IModRegistry registry )
@@ -219,5 +222,6 @@ public class JEIPlugin implements IModPlugin
{
JEIModule jeiModule = (JEIModule) Integrations.jei();
jeiModule.setJei( new JeiRuntimeAdapter( jeiRuntime ) );
runtime = jeiRuntime;
}
}
@@ -93,6 +93,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
private final List<TileCraftingTile> storage = new ArrayList<>();
private final List<TileCraftingMonitorTile> status = new ArrayList<>();
private final HashMap<IMEMonitorHandlerReceiver<IAEItemStack>, Object> listeners = new HashMap<>();
private final Map<ICraftingPatternDetails,List<ICraftingMedium>> visitedMediums = new HashMap<>();
private ICraftingLink myLastLink;
private String myName = "";
private boolean isDestroyed = false;
@@ -653,6 +654,23 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
continue;
}
if (visitedMediums.containsKey( details ))
{
if( visitedMediums.get( details ).containsAll( cc.getMediums( e.getKey() ) ) )
{
visitedMediums.clear();
visitedMediums.put( details, new ArrayList<>() );
}
}
visitedMediums.putIfAbsent( details, new ArrayList<>() );
if( visitedMediums.get( details ).contains( m ) )
{
continue;
}
visitedMediums.get( details ).add( m );
if( !m.isBusy() )
{
if( ic == null )
@@ -6,7 +6,6 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import appeng.api.storage.IStorageChannel;
@@ -14,7 +13,6 @@ import appeng.api.storage.IStorageChannel;
import appeng.core.AELog;
import com.jaquadro.minecraft.storagedrawers.api.capabilities.IItemRepository;
import net.minecraft.item.ItemStack;
import net.minecraft.util.NonNullList;
import appeng.api.AEApi;
import appeng.api.config.Actionable;
@@ -401,10 +401,13 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
}
// Check via cap for IItemRepository
IItemRepository handlerRepo = target.getCapability( ITEM_REPOSITORY_CAPABILITY, targetSide );
if( handlerRepo != null )
if (ITEM_REPOSITORY_CAPABILITY != null && target.hasCapability( ITEM_REPOSITORY_CAPABILITY, targetSide ))
{
return new ItemRepositoryAdapter( handlerRepo, this );
IItemRepository handlerRepo = target.getCapability( ITEM_REPOSITORY_CAPABILITY, targetSide );
if( handlerRepo != null )
{
return new ItemRepositoryAdapter( handlerRepo, this );
}
}
// Check via cap for IItemHandler
IItemHandler handlerExt = target.getCapability( CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, targetSide );
@@ -431,11 +434,14 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
return Objects.hash( target, target.getCapability( Capabilities.STORAGE_MONITORABLE_ACCESSOR, targetSide ) );
}
final IItemRepository handlerRepo = target.getCapability( ITEM_REPOSITORY_CAPABILITY, targetSide );
if( handlerRepo != null )
if (ITEM_REPOSITORY_CAPABILITY != null && target.hasCapability( ITEM_REPOSITORY_CAPABILITY, targetSide ))
{
return Objects.hash( target, handlerRepo, handlerRepo.getAllItems().size() );
final IItemRepository handlerRepo = target.getCapability( ITEM_REPOSITORY_CAPABILITY, targetSide );
if( handlerRepo != null )
{
return Objects.hash( target, handlerRepo, handlerRepo.getAllItems().size() );
}
}
final IItemHandler itemHandler = target.getCapability( CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, targetSide );
@@ -47,7 +47,7 @@ public abstract class InventoryAdaptor implements Iterable<ItemSlot>
{
if( te != null )
{
if( te.hasCapability( ITEM_REPOSITORY_CAPABILITY, d ) )
if( ITEM_REPOSITORY_CAPABILITY != null && te.hasCapability( ITEM_REPOSITORY_CAPABILITY, d ) )
{
IItemRepository itemRepository = te.getCapability( ITEM_REPOSITORY_CAPABILITY, d );
if (itemRepository != null){