diff --git a/src/main/java/appeng/client/gui/AEBaseGui.java b/src/main/java/appeng/client/gui/AEBaseGui.java index de1448f0a..6a7041886 100644 --- a/src/main/java/appeng/client/gui/AEBaseGui.java +++ b/src/main/java/appeng/client/gui/AEBaseGui.java @@ -106,6 +106,12 @@ public abstract class AEBaseGui extends GuiContainer implements IMTModGuiContain private Stopwatch dbl_clickTimer = Stopwatch.createStarted(); private ItemStack dbl_whichItem = ItemStack.EMPTY; private Slot bl_clicked; + + public List getGuiSlots() + { + return guiSlots; + } + protected final List guiSlots = new ArrayList<>(); public AEBaseGui( final Container container ) diff --git a/src/main/java/appeng/client/gui/AEGuiHandler.java b/src/main/java/appeng/client/gui/AEGuiHandler.java index 749ae4a85..22bc1a32e 100644 --- a/src/main/java/appeng/client/gui/AEGuiHandler.java +++ b/src/main/java/appeng/client/gui/AEGuiHandler.java @@ -2,24 +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.*; +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 net.minecraftforge.fluids.FluidStack; import java.awt.*; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.List; -public class AEGuiHandler implements IAdvancedGuiHandler +public class AEGuiHandler implements IAdvancedGuiHandler, IGhostIngredientHandler { @Override @@ -39,7 +38,7 @@ public class AEGuiHandler implements IAdvancedGuiHandler @Override public Object getIngredientUnderMouse( AEBaseGui guiContainer, int mouseX, int mouseY ) { - List visual = new ArrayList<>(); + List visual; int guiSlotIdx = 0; Object result = null; if( guiContainer instanceof GuiCraftConfirm ) @@ -94,4 +93,57 @@ public class AEGuiHandler implements IAdvancedGuiHandler if( guiSloty > ( rows - 1 ) || mouseY < guitop + yo ) return -1; return ( guiSloty * 3 ) + guiSlotx + ( currentScroll * 3 ); } + + @Override + public List> getTargets( AEBaseGui gui, I ingredient, boolean doStart ) + { + ArrayList> targets = new ArrayList<>(); + if( gui instanceof IJEIGhostIngredients ) + { + IJEIGhostIngredients g = (IJEIGhostIngredients) gui; + List> phantomTargets = g.getPhantomTargets( ingredient ); + targets.addAll( (List>) (Object) phantomTargets ); + } + if( doStart ) + { + if( GuiScreen.isShiftKeyDown() ) + { + if( gui instanceof GuiUpgradeable || gui instanceof GuiPatternTerm ) + { + IJEIGhostIngredients ghostGui = ( (IJEIGhostIngredients) gui ); + for( Target 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; + } + } diff --git a/src/main/java/appeng/client/gui/implementations/GuiPatternTerm.java b/src/main/java/appeng/client/gui/implementations/GuiPatternTerm.java index ffaa435b3..b61cee120 100644 --- a/src/main/java/appeng/client/gui/implementations/GuiPatternTerm.java +++ b/src/main/java/appeng/client/gui/implementations/GuiPatternTerm.java @@ -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,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> getPhantomTargets(Object ingredient) { + if (!(ingredient instanceof ItemStack )) { + return Collections.emptyList(); + } + List> targets = new ArrayList<>(); + for( Slot slot : this.inventorySlots.inventorySlots ) + { + if( slot instanceof SlotFake ) + { + ItemStack itemStack = (ItemStack) ingredient; + Target target = new Target() + { + @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, Object> getFakeSlotTargetMap() + { + return mapTargetSlot; + } } diff --git a/src/main/java/appeng/client/gui/implementations/GuiUpgradeable.java b/src/main/java/appeng/client/gui/implementations/GuiUpgradeable.java index c2cff22d3..7e6f7f5c3 100644 --- a/src/main/java/appeng/client/gui/implementations/GuiUpgradeable.java +++ b/src/main/java/appeng/client/gui/implementations/GuiUpgradeable.java @@ -19,8 +19,29 @@ 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.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.block.Block; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.fluids.BlockFluidBase; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidRegistry; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import org.lwjgl.input.Mouse; import net.minecraft.client.gui.GuiButton; @@ -43,9 +64,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,Object> mapTargetSlot = new HashMap<>(); protected final ContainerUpgradeable cvb; protected final IUpgradeableHost bc; @@ -200,4 +221,127 @@ public class GuiUpgradeable extends AEBaseGui NetworkHandler.instance().sendToServer( new PacketConfigButton( this.schedulingMode.getSetting(), backwards ) ); } } + + @Override + public List> getPhantomTargets(Object ingredient) + { + mapTargetSlot.clear(); + + FluidStack fluidStack = null; + ItemStack itemStack = ItemStack.EMPTY; + + if( ingredient instanceof ItemStack ) + { + itemStack = (ItemStack) ingredient; + + if( itemStack.hasCapability( CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, null ) ) + { + fluidStack = ( itemStack.getCapability( CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, null ).drain( Integer.MAX_VALUE, false ) ); + } + if( fluidStack == null ) + { + NBTTagCompound tagCompound = itemStack.getTagCompound(); + if( tagCompound != null && tagCompound.hasKey( "Fluid" ) ) + { + Fluid fluid = FluidRegistry.getFluid( tagCompound.getString( "Fluid" ) ); + fluidStack = new FluidStack( fluid, 1000 ); + } + } + if( fluidStack == null ) + { + Block maybeFluidBlock = Block.getBlockFromItem( itemStack.getItem() ); + if( Block.getBlockFromItem( itemStack.getItem() ) instanceof BlockFluidBase ) + { + Fluid fluid = ( (BlockFluidBase) maybeFluidBlock ).getFluid(); + fluidStack = new FluidStack( fluid, 1000 ); + } + } + } + else if( ingredient instanceof FluidStack ) + { + fluidStack = (FluidStack) ingredient; + } + + List> targets = new ArrayList<>(); + + if( !itemStack.isEmpty() ) + { + for( Slot slot : this.inventorySlots.inventorySlots ) + { + if( slot instanceof SlotFake ) + { + ItemStack finalItemStack = itemStack; + Target targetItem = new Target() + { + @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( finalItemStack ) ); + NetworkHandler.instance().sendToServer( p ); + + } + catch( IOException e ) + { + e.printStackTrace(); + } + } + }; + targets.add( targetItem ); + mapTargetSlot.putIfAbsent( targetItem, slot ); + } + } + } + if( fluidStack != null ) + { + for( GuiCustomSlot guiCustomSlot : this.guiSlots ) + { + if( guiCustomSlot instanceof GuiFluidSlot ) + { + FluidStack finalFluidStack = fluidStack; + Target targetFluid = new Target() + { + @Override + public Rectangle getArea() + { + return new Rectangle( getGuiLeft() + guiCustomSlot.xPos(), getGuiTop() + guiCustomSlot.yPos(), 16, 16 ); + } + + @Override + public void accept( Object ingredient ) + { + final PacketInventoryAction p; + try + { + p = new PacketInventoryAction( InventoryAction.PLACE_JEI_GHOST_ITEM, (GuiFluidSlot) guiCustomSlot, AEFluidStack.fromFluidStack( finalFluidStack ) ); + NetworkHandler.instance().sendToServer( p ); + + } + catch( IOException e ) + { + e.printStackTrace(); + } + } + }; + targets.add( targetFluid ); + mapTargetSlot.putIfAbsent( targetFluid, guiCustomSlot ); + } + } + } + return targets; + } + + @Override + public Map, Object> getFakeSlotTargetMap() + { + return mapTargetSlot; + } } diff --git a/src/main/java/appeng/container/interfaces/IJEIGhostIngredients.java b/src/main/java/appeng/container/interfaces/IJEIGhostIngredients.java new file mode 100644 index 000000000..f70eb0630 --- /dev/null +++ b/src/main/java/appeng/container/interfaces/IJEIGhostIngredients.java @@ -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> getPhantomTargets( Object ingredient ); + + default Map, Object> getFakeSlotTargetMap(){ + return new HashMap<>(); + } + +} \ No newline at end of file diff --git a/src/main/java/appeng/core/sync/packets/PacketInventoryAction.java b/src/main/java/appeng/core/sync/packets/PacketInventoryAction.java index 0bb0dc71f..3feeaf6df 100644 --- a/src/main/java/appeng/core/sync/packets/PacketInventoryAction.java +++ b/src/main/java/appeng/core/sync/packets/PacketInventoryAction.java @@ -21,9 +21,17 @@ package appeng.core.sync.packets; import java.io.IOException; +import appeng.api.storage.data.IAEFluidStack; +import appeng.client.gui.implementations.GuiUpgradeable; +import appeng.client.gui.widgets.GuiCustomSlot; +import appeng.container.slot.SlotFake; +import appeng.fluids.client.gui.GuiFluidInterface; +import appeng.fluids.client.gui.widgets.GuiFluidSlot; +import appeng.fluids.util.AEFluidStack; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; +import net.minecraft.client.Minecraft; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemStack; @@ -49,6 +57,7 @@ public class PacketInventoryAction extends AppEngPacket private final int slot; private final long id; private final IAEItemStack slotItem; + private final IAEFluidStack slotFluid; // automatic. public PacketInventoryAction( final ByteBuf stream ) throws IOException @@ -57,6 +66,8 @@ public class PacketInventoryAction extends AppEngPacket this.slot = stream.readInt(); this.id = stream.readLong(); final boolean hasItem = stream.readBoolean(); + final boolean hasFluid = stream.readBoolean(); + if( hasItem ) { this.slotItem = AEItemStack.fromPacket( stream ); @@ -65,12 +76,19 @@ public class PacketInventoryAction extends AppEngPacket { this.slotItem = null; } + if( hasFluid ) + { + this.slotFluid = AEFluidStack.fromPacket( stream ); + } + else + { + this.slotFluid = null; + } } // 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." ); @@ -80,6 +98,7 @@ public class PacketInventoryAction extends AppEngPacket this.slot = slot; this.id = 0; this.slotItem = slotItem; + this.slotFluid = null; final ByteBuf data = Unpooled.buffer(); @@ -91,16 +110,88 @@ public class PacketInventoryAction extends AppEngPacket if( slotItem == null ) { data.writeBoolean( false ); + data.writeBoolean( false ); } else { data.writeBoolean( true ); + data.writeBoolean( false ); slotItem.writeToPacket( data ); } this.configureWrite( data ); } + public PacketInventoryAction( final InventoryAction action, final SlotFake slot, final IAEItemStack slotItem ) throws IOException + { + if( action != InventoryAction.PLACE_JEI_GHOST_ITEM ) + { + throw new IllegalStateException( "invalid packet, client cannot post inv actions with stacks." ); + } + + this.action = action; + this.slot = slot.slotNumber; + this.id = 0; + this.slotItem = slotItem; + this.slotFluid = null; + + final ByteBuf data = Unpooled.buffer(); + + data.writeInt( this.getPacketID() ); + data.writeInt( action.ordinal() ); + data.writeInt( slot.slotNumber ); + data.writeLong( this.id ); + + if( slotItem == null ) + { + data.writeBoolean( false ); + data.writeBoolean( false ); + } + else + { + data.writeBoolean( true ); + data.writeBoolean( false ); + slotItem.writeToPacket( data ); + } + + + this.configureWrite( data ); + } + + public PacketInventoryAction( final InventoryAction action, final GuiFluidSlot slot, final IAEFluidStack slotFluid ) throws IOException + { + if( action != InventoryAction.PLACE_JEI_GHOST_ITEM ) + { + throw new IllegalStateException( "invalid packet, client cannot post inv actions with stacks." ); + } + + this.action = action; + this.slot = slot.getId(); + this.id = 2; + this.slotFluid = slotFluid; + this.slotItem = null; + + final ByteBuf data = Unpooled.buffer(); + + data.writeInt( this.getPacketID() ); + data.writeInt( action.ordinal() ); + data.writeInt( slot.getId() ); + data.writeLong( this.id ); + data.writeBoolean( false ); + + if( slotFluid == null ) + { + data.writeBoolean( false ); + } + else + { + data.writeBoolean( true ); + slotFluid.writeToPacket( data ); + } + + this.configureWrite( data ); + } + // api public PacketInventoryAction( final InventoryAction action, final int slot, final long id ) { @@ -108,6 +199,7 @@ public class PacketInventoryAction extends AppEngPacket this.slot = slot; this.id = id; this.slotItem = null; + this.slotFluid = null; final ByteBuf data = Unpooled.buffer(); @@ -116,6 +208,7 @@ public class PacketInventoryAction extends AppEngPacket data.writeInt( slot ); data.writeLong( id ); data.writeBoolean( false ); + data.writeBoolean( false ); this.configureWrite( data ); } @@ -150,6 +243,38 @@ 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() ); + else sender.openContainer.inventorySlots.get( this.slot ).putStack( ItemStack.EMPTY ); + } + if( Minecraft.getMinecraft().currentScreen instanceof GuiUpgradeable ) + { + GuiUpgradeable cs = ( (GuiUpgradeable) Minecraft.getMinecraft().currentScreen ); + if( cs.getGuiSlots().size() > 0 ) + { + GuiCustomSlot ct = cs.getGuiSlots().get( this.slot ); + if( this.slotFluid != null ) + { + if( ct instanceof GuiFluidSlot ) + { + GuiFluidSlot gfs = (GuiFluidSlot) ct; + gfs.setFluidStack( this.slotFluid ); + } + } + else + { + if( ct instanceof GuiFluidSlot ) + { + GuiFluidSlot gfs = (GuiFluidSlot) ct; + gfs.setFluidStack( null ); + } + } + } + } + } else { baseContainer.doAction( sender, this.action, this.slot, this.id ); diff --git a/src/main/java/appeng/helpers/InventoryAction.java b/src/main/java/appeng/helpers/InventoryAction.java index 697ea0b08..6c545e8c8 100644 --- a/src/main/java/appeng/helpers/InventoryAction.java +++ b/src/main/java/appeng/helpers/InventoryAction.java @@ -43,5 +43,6 @@ public enum InventoryAction ROLL_UP, ROLL_DOWN, AUTO_CRAFT, - PLACE_SINGLE + PLACE_SINGLE, + PLACE_JEI_GHOST_ITEM } diff --git a/src/main/java/appeng/integration/modules/jei/JEIPlugin.java b/src/main/java/appeng/integration/modules/jei/JEIPlugin.java index 50e048d50..50f98c693 100644 --- a/src/main/java/appeng/integration/modules/jei/JEIPlugin.java +++ b/src/main/java/appeng/integration/modules/jei/JEIPlugin.java @@ -97,6 +97,7 @@ public class JEIPlugin implements IModPlugin AEGuiHandler aeGuiHandler = new AEGuiHandler(); registry.addAdvancedGuiHandlers(aeGuiHandler); + registry.addGhostIngredientHandler( aeGuiHandler.getGuiContainerClass(), aeGuiHandler); } private void registerDescriptions( IDefinitions definitions, IModRegistry registry )