Skip to content

Commit 974d20f

Browse files
authored
Merge pull request #167 from Alecsioo/improve_jei_integration_machinery
Improved JEI integration for machinery item input hatches
2 parents f4b9006 + e278158 commit 974d20f

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)