Skip to content

Commit e278158

Browse files
committed
Implemented JEI drag and drop while in the machinery item input hatch GUI and recipe transfer from JEI to configured machinery item input slots
1 parent e4349ad commit e278158

File tree

6 files changed

+312
-8
lines changed

6 files changed

+312
-8
lines changed

src/main/java/github/kasuminova/mmce/client/gui/GuiMEItemInputBus.java

Lines changed: 92 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,23 @@
11
package github.kasuminova.mmce.client.gui;
22

3+
import appeng.container.interfaces.IJEIGhostIngredients;
4+
import appeng.container.slot.IJEITargetSlot;
35
import appeng.container.slot.SlotDisabled;
46
import appeng.container.slot.SlotFake;
57
import appeng.core.localization.GuiText;
8+
import appeng.core.sync.network.NetworkHandler;
9+
import appeng.core.sync.packets.PacketInventoryAction;
10+
import appeng.fluids.client.gui.widgets.GuiFluidSlot;
11+
import appeng.fluids.util.AEFluidStack;
12+
import appeng.helpers.InventoryAction;
13+
import appeng.util.item.AEItemStack;
614
import github.kasuminova.mmce.common.container.ContainerMEItemInputBus;
715
import github.kasuminova.mmce.common.network.PktMEInputBusInvAction;
816
import github.kasuminova.mmce.common.tile.MEItemInputBus;
917
import hellfirepvp.modularmachinery.ModularMachinery;
1018
import hellfirepvp.modularmachinery.client.ClientProxy;
1119
import hellfirepvp.modularmachinery.common.util.MiscUtils;
20+
import mezz.jei.api.gui.IGhostIngredientHandler;
1221
import net.minecraft.client.gui.FontRenderer;
1322
import net.minecraft.client.renderer.GlStateManager;
1423
import net.minecraft.client.resources.I18n;
@@ -17,20 +26,23 @@
1726
import net.minecraft.item.ItemStack;
1827
import net.minecraft.util.ResourceLocation;
1928
import net.minecraft.util.text.TextFormatting;
29+
import net.minecraftforge.fluids.FluidStack;
30+
import net.minecraftforge.fluids.FluidUtil;
2031
import net.minecraftforge.fml.client.config.GuiUtils;
2132
import org.lwjgl.input.Keyboard;
2233
import org.lwjgl.input.Mouse;
2334

2435
import javax.annotation.Nonnull;
36+
import java.awt.*;
2537
import java.io.IOException;
2638
import java.text.NumberFormat;
27-
import java.util.ArrayList;
39+
import java.util.*;
2840
import java.util.List;
29-
import java.util.Locale;
3041

31-
public class GuiMEItemInputBus extends GuiMEItemBus {
42+
public class GuiMEItemInputBus extends GuiMEItemBus implements IJEIGhostIngredients {
3243
private static final ResourceLocation TEXTURES_INPUT_BUS = new ResourceLocation(ModularMachinery.MODID, "textures/gui/meiteminputbus.png");
3344

45+
protected final Map<IGhostIngredientHandler.Target<?>, Object> mapTargetSlot = new HashMap<>();
3446
private int invActionAmount = 0;
3547

3648
public GuiMEItemInputBus(final MEItemInputBus te, final EntityPlayer player) {
@@ -209,4 +221,81 @@ protected void renderToolTip(@Nonnull final ItemStack stack, final int x, final
209221
this.drawHoveringText(tooltip, x, y, (font == null ? fontRenderer : font));
210222
GuiUtils.postItemToolTip();
211223
}
224+
225+
// Code adapted from appeng.client.gui.implementations.GuiUpgradeable, full credits to the original author
226+
@Override
227+
public List<IGhostIngredientHandler.Target<?>> getPhantomTargets(Object ingredient) {
228+
mapTargetSlot.clear();
229+
230+
FluidStack fluidStack = null;
231+
ItemStack itemStack = ItemStack.EMPTY;
232+
233+
if (ingredient instanceof ItemStack) {
234+
itemStack = (ItemStack) ingredient;
235+
fluidStack = FluidUtil.getFluidContained(itemStack);
236+
} else if (ingredient instanceof FluidStack) {
237+
fluidStack = (FluidStack) ingredient;
238+
}
239+
240+
if (!(ingredient instanceof ItemStack) && !(ingredient instanceof FluidStack)) {
241+
return Collections.emptyList();
242+
}
243+
244+
List<IGhostIngredientHandler.Target<?>> targets = new ArrayList();
245+
List<IJEITargetSlot> slots = new ArrayList();
246+
if (!this.inventorySlots.inventorySlots.isEmpty()) {
247+
for(Slot slot : this.inventorySlots.inventorySlots) {
248+
if (slot instanceof SlotFake && (!itemStack.isEmpty())) {
249+
slots.add((IJEITargetSlot)slot);
250+
}
251+
}
252+
}
253+
for (IJEITargetSlot slot : slots) {
254+
ItemStack finalItemStack = itemStack;
255+
FluidStack finalFluidStack = fluidStack;
256+
IGhostIngredientHandler.Target<Object> targetItem = new IGhostIngredientHandler.Target<>() {
257+
@Nonnull
258+
@Override
259+
public Rectangle getArea() {
260+
if (slot instanceof SlotFake && ((SlotFake) slot).isSlotEnabled()) {
261+
return new Rectangle(getGuiLeft() + ((SlotFake) slot).xPos, getGuiTop() + ((SlotFake) slot).yPos, 16, 16);
262+
} else if (slot instanceof GuiFluidSlot && ((GuiFluidSlot) slot).isSlotEnabled()) {
263+
return new Rectangle(getGuiLeft() + ((GuiFluidSlot) slot).xPos(), getGuiTop() + ((GuiFluidSlot) slot).yPos(), 16, 16);
264+
}
265+
return new Rectangle();
266+
}
267+
268+
@Override
269+
public void accept(@Nonnull Object ingredient) {
270+
PacketInventoryAction p = null;
271+
try {
272+
if (slot instanceof SlotFake && ((SlotFake) slot).isSlotEnabled()) {
273+
if (finalItemStack.isEmpty() && finalFluidStack != null) {
274+
p = new PacketInventoryAction(InventoryAction.PLACE_JEI_GHOST_ITEM, slot, AEItemStack.fromItemStack(FluidUtil.getFilledBucket(finalFluidStack)));
275+
} else if (!finalItemStack.isEmpty()) {
276+
p = new PacketInventoryAction(InventoryAction.PLACE_JEI_GHOST_ITEM, slot, AEItemStack.fromItemStack(finalItemStack));
277+
}
278+
} else {
279+
if (finalFluidStack == null) {
280+
return;
281+
}
282+
p = new PacketInventoryAction(InventoryAction.PLACE_JEI_GHOST_ITEM, slot, AEItemStack.fromItemStack(AEFluidStack.fromFluidStack(finalFluidStack).asItemStackRepresentation()));
283+
}
284+
NetworkHandler.instance().sendToServer(p);
285+
286+
} catch (IOException e) {
287+
e.printStackTrace();
288+
}
289+
}
290+
};
291+
targets.add(targetItem);
292+
mapTargetSlot.putIfAbsent(targetItem, slot);
293+
}
294+
return targets;
295+
}
296+
297+
@Override
298+
public Map<IGhostIngredientHandler.Target<?>, Object> getFakeSlotTargetMap() {
299+
return mapTargetSlot;
300+
}
212301
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package github.kasuminova.mmce.client.gui.integration.handler;
2+
3+
import appeng.client.gui.AEGuiHandler;
4+
import appeng.container.interfaces.IJEIGhostIngredients;
5+
import appeng.container.slot.IJEITargetSlot;
6+
import github.kasuminova.mmce.client.gui.GuiMEItemInputBus;
7+
import mezz.jei.api.gui.IAdvancedGuiHandler;
8+
import mezz.jei.api.gui.IGhostIngredientHandler;
9+
import net.minecraft.client.gui.GuiScreen;
10+
import org.jetbrains.annotations.Nullable;
11+
import org.lwjgl.input.Mouse;
12+
13+
import java.awt.*;
14+
import java.util.ArrayList;
15+
import java.util.List;
16+
17+
public class MEInputGhostSlotHandler implements IGhostIngredientHandler<GuiMEItemInputBus>, IAdvancedGuiHandler<GuiMEItemInputBus> {
18+
19+
private static final AEGuiHandler aeGuiHandler = new AEGuiHandler();
20+
21+
22+
@Override
23+
public <I> List<Target<I>> getTargets(GuiMEItemInputBus guiMEItemInputBus, I ingredient, boolean doStart) {
24+
ArrayList<Target<I>> targets = new ArrayList<>();
25+
IJEIGhostIngredients ghostGui = guiMEItemInputBus;
26+
List<Target<?>> phantomTargets = ghostGui.getPhantomTargets(ingredient);
27+
targets.addAll((List<Target<I>>) (Object) phantomTargets);
28+
if (doStart && GuiScreen.isShiftKeyDown() && Mouse.isButtonDown(0)) {
29+
for (Target<I> target : targets) {
30+
if (ghostGui.getFakeSlotTargetMap().get(target) instanceof IJEITargetSlot jeiSlot) {
31+
if (jeiSlot.needAccept()) {
32+
target.accept(ingredient);
33+
break;
34+
}
35+
}
36+
}
37+
}
38+
return targets;
39+
}
40+
41+
@Override
42+
public void onComplete() {
43+
44+
}
45+
46+
@Override
47+
public Class<GuiMEItemInputBus> getGuiContainerClass() {
48+
return GuiMEItemInputBus.class;
49+
}
50+
51+
@Nullable
52+
@Override
53+
public List<Rectangle> getGuiExtraAreas(GuiMEItemInputBus guiContainer) {
54+
return guiContainer.getJEIExclusionArea();
55+
}
56+
57+
@Nullable
58+
@Override
59+
public Object getIngredientUnderMouse(GuiMEItemInputBus guiContainer, int mouseX, int mouseY) {
60+
return aeGuiHandler.getIngredientUnderMouse(guiContainer, mouseX, mouseY);
61+
}
62+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package github.kasuminova.mmce.common.container.handler;
2+
3+
import github.kasuminova.mmce.common.container.ContainerMEItemInputBus;
4+
import github.kasuminova.mmce.common.network.PktMEInputBusRecipeTransfer;
5+
import hellfirepvp.modularmachinery.ModularMachinery;
6+
import mezz.jei.api.gui.IGuiIngredient;
7+
import mezz.jei.api.gui.IRecipeLayout;
8+
import mezz.jei.api.recipe.transfer.IRecipeTransferError;
9+
import mezz.jei.api.recipe.transfer.IRecipeTransferHandler;
10+
import mezz.jei.transfer.RecipeTransferErrorInternal;
11+
import net.minecraft.entity.player.EntityPlayer;
12+
import net.minecraft.item.ItemStack;
13+
import org.jetbrains.annotations.Nullable;
14+
15+
import java.util.ArrayList;
16+
import java.util.Map;
17+
18+
public class MEInputRecipeTransferHandler implements IRecipeTransferHandler<ContainerMEItemInputBus> {
19+
20+
@Override
21+
public Class<ContainerMEItemInputBus> getContainerClass() {
22+
return ContainerMEItemInputBus.class;
23+
}
24+
25+
@Nullable
26+
@Override
27+
public IRecipeTransferError transferRecipe(ContainerMEItemInputBus containerMEItemInputBus, IRecipeLayout recipeLayout, EntityPlayer entityPlayer, boolean maxTransfer, boolean doTransfer) {
28+
final String recipeType = recipeLayout.getRecipeCategory().getUid();
29+
30+
// MM recipes are identified by this prefix
31+
if (!recipeType.contains("modularmachinery.recipe")) {
32+
return RecipeTransferErrorInternal.INSTANCE;
33+
}
34+
35+
if (!doTransfer) {
36+
return null;
37+
}
38+
39+
Map<Integer, ? extends IGuiIngredient<ItemStack>> ingredients = recipeLayout.getItemStacks().getGuiIngredients();
40+
41+
ArrayList<ItemStack> inputs = new ArrayList<>();
42+
for (Map.Entry<Integer, ? extends IGuiIngredient<ItemStack>> entry : ingredients.entrySet()) {
43+
IGuiIngredient<ItemStack> ingredient = entry.getValue();
44+
// We don't care about outputs
45+
if (ingredient.isInput()) {
46+
inputs.add(ingredient.getDisplayedIngredient());
47+
}
48+
}
49+
50+
if (inputs.isEmpty()) {
51+
return RecipeTransferErrorInternal.INSTANCE;
52+
}
53+
54+
ArrayList<ItemStack> nonNullInputs = new ArrayList<>();
55+
for (ItemStack input : inputs) {
56+
if (input != null) {
57+
nonNullInputs.add(input);
58+
}
59+
}
60+
61+
PktMEInputBusRecipeTransfer pktMEInputBusRecipeTransfer = new PktMEInputBusRecipeTransfer(nonNullInputs);
62+
ModularMachinery.NET_CHANNEL.sendToServer(pktMEInputBusRecipeTransfer);
63+
64+
return null;
65+
}
66+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package github.kasuminova.mmce.common.network;
2+
3+
import appeng.container.slot.SlotFake;
4+
import appeng.helpers.ItemStackHelper;
5+
import io.netty.buffer.ByteBuf;
6+
import net.minecraft.entity.player.EntityPlayerMP;
7+
import net.minecraft.inventory.Container;
8+
import net.minecraft.inventory.Slot;
9+
import net.minecraft.item.ItemStack;
10+
import net.minecraft.nbt.NBTTagCompound;
11+
import net.minecraft.nbt.NBTTagList;
12+
import net.minecraftforge.common.util.Constants;
13+
import net.minecraftforge.fml.common.network.ByteBufUtils;
14+
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
15+
import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
16+
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
17+
18+
import java.util.ArrayList;
19+
import java.util.List;
20+
21+
public class PktMEInputBusRecipeTransfer implements IMessage, IMessageHandler<PktMEInputBusRecipeTransfer, IMessage> {
22+
23+
private ArrayList<ItemStack> inputs;
24+
25+
public PktMEInputBusRecipeTransfer() {
26+
}
27+
28+
public PktMEInputBusRecipeTransfer(ArrayList<ItemStack> inputs) {
29+
this.inputs = inputs;
30+
}
31+
32+
@Override
33+
public void fromBytes(ByteBuf buf) {
34+
inputs = new ArrayList<>();
35+
NBTTagCompound tagCompound = ByteBufUtils.readTag(buf);
36+
NBTTagList tagList = tagCompound.getTagList("itemInputs", Constants.NBT.TAG_COMPOUND);
37+
for (int i = 0; i < tagList.tagCount(); i++) {
38+
NBTTagCompound tag = tagList.getCompoundTagAt(i);
39+
if (!tagList.isEmpty()) {
40+
ItemStack stack = new ItemStack(tag);
41+
if (!stack.isEmpty()) {
42+
inputs.add(stack);
43+
}
44+
}
45+
}
46+
}
47+
48+
@Override
49+
public void toBytes(ByteBuf buf) {
50+
final NBTTagList recipeInputs = new NBTTagList();
51+
for (ItemStack input : inputs) {
52+
recipeInputs.appendTag(ItemStackHelper.stackToNBT(input));
53+
}
54+
NBTTagCompound recipeTag = new NBTTagCompound();
55+
recipeTag.setTag("itemInputs", recipeInputs);
56+
ByteBufUtils.writeTag(buf, recipeTag);
57+
}
58+
59+
@Override
60+
public IMessage onMessage(PktMEInputBusRecipeTransfer message, MessageContext ctx) {
61+
final EntityPlayerMP player = ctx.getServerHandler().player;
62+
final Container container = player.openContainer;
63+
ArrayList<ItemStack> inputs = message.inputs;
64+
List<Slot> inventorySlots = container.inventorySlots;
65+
ext:
66+
for (ItemStack input : inputs) {
67+
for (Slot slot : inventorySlots) {
68+
if (slot instanceof SlotFake slotFake) {
69+
if (!slotFake.getHasStack()) {
70+
slotFake.putStack(input.copy());
71+
continue ext;
72+
}
73+
}
74+
}
75+
}
76+
77+
return null;
78+
}
79+
}

src/main/java/hellfirepvp/modularmachinery/ModularMachinery.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,7 @@
99
package hellfirepvp.modularmachinery;
1010

1111
import github.kasuminova.mmce.common.concurrent.TaskExecutor;
12-
import github.kasuminova.mmce.common.network.PktAutoAssemblyRequest;
13-
import github.kasuminova.mmce.common.network.PktMEInputBusInvAction;
14-
import github.kasuminova.mmce.common.network.PktMEPatternProviderAction;
15-
import github.kasuminova.mmce.common.network.PktMEPatternProviderHandlerItems;
16-
import github.kasuminova.mmce.common.network.PktPerformanceReport;
12+
import github.kasuminova.mmce.common.network.*;
1713
import hellfirepvp.modularmachinery.common.CommonProxy;
1814
import hellfirepvp.modularmachinery.common.base.Mods;
1915
import hellfirepvp.modularmachinery.common.command.CommandGetBluePrint;
@@ -117,6 +113,7 @@ public void preInit(FMLPreInitializationEvent event) {
117113
NET_CHANNEL.registerMessage(PktParallelControllerUpdate.class, PktParallelControllerUpdate.class, 102, Side.SERVER);
118114
if (Mods.AE2.isPresent()) {
119115
NET_CHANNEL.registerMessage(PktMEInputBusInvAction.class, PktMEInputBusInvAction.class, 103, Side.SERVER);
116+
NET_CHANNEL.registerMessage(PktMEInputBusRecipeTransfer.class, PktMEInputBusRecipeTransfer.class, 107, Side.SERVER);
120117
}
121118
NET_CHANNEL.registerMessage(PktAutoAssemblyRequest.class, PktAutoAssemblyRequest.class, 104, Side.SERVER);
122119
if (Mods.AE2.isPresent()) {

src/main/java/hellfirepvp/modularmachinery/common/integration/ModIntegrationJEI.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
package hellfirepvp.modularmachinery.common.integration;
1010

1111
import com.google.common.collect.Lists;
12+
import github.kasuminova.mmce.client.gui.GuiMEItemInputBus;
13+
import github.kasuminova.mmce.client.gui.integration.handler.MEInputGhostSlotHandler;
14+
import github.kasuminova.mmce.common.container.handler.MEInputRecipeTransferHandler;
1215
import hellfirepvp.modularmachinery.ModularMachinery;
1316
import hellfirepvp.modularmachinery.common.base.Mods;
1417
import hellfirepvp.modularmachinery.common.block.BlockController;
@@ -204,6 +207,14 @@ public void register(IModRegistry registry) {
204207
registry.addRecipeCatalyst(stack, machineCategory);
205208
}
206209

210+
registry.addGhostIngredientHandler(GuiMEItemInputBus.class, new MEInputGhostSlotHandler());
211+
212+
// Only handle MM recipes
213+
for (DynamicMachine machine : MachineRegistry.getRegistry()) {
214+
String machineCategory = getCategoryStringFor(machine);
215+
registry.getRecipeTransferRegistry().addRecipeTransferHandler(new MEInputRecipeTransferHandler(), machineCategory);
216+
}
217+
207218
for (DynamicMachine machine : MachineRegistry.getRegistry()) {
208219
PREVIEW_WRAPPERS.add(new StructurePreviewWrapper(machine));
209220
}

0 commit comments

Comments
 (0)