Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NEI Bookmark Pulling for AE2 #372

Merged
merged 7 commits into from
Sep 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,10 @@ public boolean isAPatternTerminal() {
return false;
}

public IMEMonitor<IAEItemStack> getMonitor() {
return monitor;
}

// to avoid duplicating this method in 2 pattern terminals
protected void refillBlankPatterns(Slot slot) {
if (Platform.isServer()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,8 @@ public void detectAndSendChanges() {
this.setPowerMultiplier(AEConfig.instance.wireless_getDrainRate(this.wirelessTerminalGUIObject.getRange()));
}
}

public WirelessTerminalGuiObject getWirelessTerminalGUIObject() {
return this.wirelessTerminalGUIObject;
}
}
4 changes: 3 additions & 1 deletion src/main/java/appeng/core/sync/AppEngPacketHandlerBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import appeng.core.sync.packets.PacketMatterCannon;
import appeng.core.sync.packets.PacketMockExplosion;
import appeng.core.sync.packets.PacketMultiPart;
import appeng.core.sync.packets.PacketNEIBookmark;
import appeng.core.sync.packets.PacketNEIDragClick;
import appeng.core.sync.packets.PacketNEIRecipe;
import appeng.core.sync.packets.PacketNewStorageDimension;
Expand Down Expand Up @@ -108,7 +109,8 @@ public enum PacketTypes {
PACKET_PATTERN_VALUE(PacketPatternValueSet.class),
PACKET_CRAFTING_REMAINING_OPERATIONS(PacketCraftingRemainingOperations.class),
PACKET_CRAFTING_ITEM_INTERFACE(PacketCraftingItemInterface.class),
PACKET_CRAFTING_TREE_DATA(PacketCraftingTreeData.class);
PACKET_CRAFTING_TREE_DATA(PacketCraftingTreeData.class),
PACKET_NEI_BOOKMARK(PacketNEIBookmark.class);

private final Class<? extends AppEngPacket> packetClass;
private final Constructor<? extends AppEngPacket> packetConstructor;
Expand Down
101 changes: 101 additions & 0 deletions src/main/java/appeng/core/sync/packets/PacketNEIBookmark.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package appeng.core.sync.packets;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;

import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.inventory.Container;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompressedStreamTools;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.common.util.ForgeDirection;

import appeng.api.networking.energy.IEnergySource;
import appeng.api.networking.security.BaseActionSource;
import appeng.api.storage.IMEMonitor;
import appeng.api.storage.data.IAEItemStack;
import appeng.container.implementations.ContainerMEMonitorable;
import appeng.core.sync.AppEngPacket;
import appeng.core.sync.network.INetworkInfo;
import appeng.util.InventoryAdaptor;
import appeng.util.Platform;
import appeng.util.item.AEItemStack;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;

public class PacketNEIBookmark extends AppEngPacket {

private ItemStack bookmarkItem;

// automatic
public PacketNEIBookmark(final ByteBuf stream) throws IOException {
final ByteArrayInputStream bytes = new ByteArrayInputStream(stream.array());
bytes.skip(stream.readerIndex());
final NBTTagCompound comp = CompressedStreamTools.readCompressed(bytes);
if (comp != null) {
this.bookmarkItem = ItemStack.loadItemStackFromNBT(comp);
}
}

// api
public PacketNEIBookmark(final NBTTagCompound bookmarkItemComp) throws IOException {
final ByteBuf data = Unpooled.buffer();

final ByteArrayOutputStream bytes = new ByteArrayOutputStream();
final DataOutputStream outputStream = new DataOutputStream(bytes);

data.writeInt(this.getPacketID());

CompressedStreamTools.writeCompressed(bookmarkItemComp, outputStream);
data.writeBytes(bytes.toByteArray());

this.configureWrite(data);
}

@Override
public void serverPacketData(final INetworkInfo manager, final AppEngPacket packet, final EntityPlayer player) {
bookmarkItem.stackSize = fitStack(player, bookmarkItem);
final EntityPlayerMP pmp = (EntityPlayerMP) player;
final Container con = pmp.openContainer;

if (con instanceof ContainerMEMonitorable monitorable) {
final IMEMonitor<IAEItemStack> monitor = monitorable.getMonitor();
if (monitor != null) {
final IEnergySource energy = monitorable.getPowerSource();
final BaseActionSource actionSource = monitorable.getActionSource();

final AEItemStack request = AEItemStack.create(bookmarkItem);
final IAEItemStack out = Platform.poweredExtraction(energy, monitor, request, actionSource);
if (out != null) {
final InventoryAdaptor adp = InventoryAdaptor.getAdaptor(player, ForgeDirection.UNKNOWN);
ItemStack outItem = out.getItemStack();
adp.addItems(outItem);
}
}
}
}

private int fitStack(final EntityPlayer player, ItemStack itemStack) {
// Check if the bookmark item fits fully or partially into the inventory
// itemStack will always be <= maxStackSize because of how the packets are received
ItemStack[] inv = player.inventory.mainInventory;
int remainingStackSize = itemStack.stackSize; // We want to fit this
for (ItemStack slotStack : inv) {
if (slotStack == null) { // Empty slot, stack fits completely
return itemStack.stackSize;
} else if (slotStack.isItemEqual(itemStack)) {
remainingStackSize -= itemStack.getMaxStackSize() - slotStack.stackSize;
if (remainingStackSize < 0) {
return itemStack.stackSize;
}
}
}
if (remainingStackSize == itemStack.getMaxStackSize()) {
return 0; // Stack didn't fit at all
}
return itemStack.stackSize - remainingStackSize;
}
}
31 changes: 30 additions & 1 deletion src/main/java/appeng/integration/modules/NEI.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,22 @@
import appeng.client.gui.implementations.GuiCraftConfirm;
import appeng.client.gui.implementations.GuiCraftingCPU;
import appeng.client.gui.implementations.GuiCraftingTerm;
import appeng.client.gui.implementations.GuiMEMonitorable;
import appeng.client.gui.implementations.GuiMEPortableCell;
import appeng.client.gui.implementations.GuiPatternTerm;
import appeng.client.gui.implementations.GuiPatternTermEx;
import appeng.client.gui.implementations.GuiSkyChest;
import appeng.client.gui.implementations.GuiWirelessTerm;
import appeng.core.AEConfig;
import appeng.core.features.AEFeature;
import appeng.helpers.Reflected;
import appeng.integration.IIntegrationModule;
import appeng.integration.IntegrationHelper;
import appeng.integration.abstraction.INEI;
import appeng.integration.modules.NEIHelpers.NEIAEBookmarkContainerHandler;
import appeng.integration.modules.NEIHelpers.NEIAEShapedRecipeHandler;
import appeng.integration.modules.NEIHelpers.NEIAEShapelessRecipeHandler;
import appeng.integration.modules.NEIHelpers.NEIAETerminalBookmarkContainerHandler;
import appeng.integration.modules.NEIHelpers.NEICraftingHandler;
import appeng.integration.modules.NEIHelpers.NEIFacadeRecipeHandler;
import appeng.integration.modules.NEIHelpers.NEIGrinderRecipeHandler;
Expand All @@ -46,6 +53,7 @@
import codechicken.nei.ItemsGrid;
import codechicken.nei.LayoutManager;
import codechicken.nei.SearchField.ISearchProvider;
import codechicken.nei.api.IBookmarkContainerHandler;
import codechicken.nei.api.INEIGuiHandler;
import codechicken.nei.api.IStackPositioner;
import codechicken.nei.guihook.GuiContainerManager;
Expand All @@ -64,6 +72,7 @@ public class NEI implements INEI, IContainerTooltipHandler, IIntegrationModule,
private Method registerUsageHandler;
private Method registerNEIGuiHandler;
private Method registerItemFilter;
private Method registerBookmarkContainerHandler;

@Reflected
public NEI() throws ClassNotFoundException {
Expand All @@ -73,6 +82,7 @@ public NEI() throws ClassNotFoundException {
IntegrationHelper.testClassExistence(this, IContainerTooltipHandler.class);
IntegrationHelper.testClassExistence(this, codechicken.nei.recipe.ICraftingHandler.class);
IntegrationHelper.testClassExistence(this, codechicken.nei.recipe.IUsageHandler.class);
IntegrationHelper.testClassExistence(this, codechicken.nei.api.IBookmarkContainerHandler.class);

this.apiClass = Class.forName("codechicken.nei.api.API");
}
Expand All @@ -98,7 +108,26 @@ public void init() throws Throwable {
&& AEConfig.instance.isFeatureEnabled(AEFeature.EnableFacadeCrafting)) {
this.registerRecipeHandler(new NEIFacadeRecipeHandler());
}

this.registerBookmarkContainerHandler = this.apiClass
.getDeclaredMethod("registerBookmarkContainerHandler", Class.class, IBookmarkContainerHandler.class);
this.registerBookmarkContainerHandler.invoke(apiClass, GuiSkyChest.class, new NEIAEBookmarkContainerHandler()); // Skystone
// chests
this.registerBookmarkContainerHandler
.invoke(apiClass, GuiCraftingTerm.class, new NEIAETerminalBookmarkContainerHandler()); // Crafting
// Terminal
this.registerBookmarkContainerHandler
.invoke(apiClass, GuiMEMonitorable.class, new NEIAETerminalBookmarkContainerHandler()); // Terminal
this.registerBookmarkContainerHandler
.invoke(apiClass, GuiWirelessTerm.class, new NEIAETerminalBookmarkContainerHandler()); // Wireless
// Terminal
firenoo marked this conversation as resolved.
Show resolved Hide resolved
this.registerBookmarkContainerHandler
.invoke(apiClass, GuiPatternTerm.class, new NEIAETerminalBookmarkContainerHandler()); // Pattern
// terminal
this.registerBookmarkContainerHandler
.invoke(apiClass, GuiPatternTermEx.class, new NEIAETerminalBookmarkContainerHandler()); // Big pattern
// terminal
this.registerBookmarkContainerHandler
.invoke(apiClass, GuiMEPortableCell.class, new NEIAETerminalBookmarkContainerHandler()); // ME chest
// large stack tooltips
GuiContainerManager.addTooltipHandler(this);
GuiContainerManager.addObjectHandler(this);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package appeng.integration.modules.NEIHelpers;

import java.util.ArrayList;
import java.util.List;

import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.inventory.Container;
import net.minecraft.item.ItemStack;

import codechicken.nei.api.IBookmarkContainerHandler;

public class NEIAEBookmarkContainerHandler implements IBookmarkContainerHandler {

protected static Minecraft mc = Minecraft.getMinecraft();

@Override
public void pullBookmarkItemsFromContainer(GuiContainer guiContainer, ArrayList<ItemStack> bookmarkItems) {
List<ItemStack> containerStacks = guiContainer.inventorySlots.getInventory();
for (ItemStack bookmarkItem : bookmarkItems) {

int bookmarkSizeBackup = bookmarkItem.stackSize;

for (int i = 0; i < containerStacks.size() - 4 * 9; i++) {
ItemStack containerItem = containerStacks.get(i);

if (containerItem == null) {
continue;
}

if (bookmarkItem.isItemEqual(containerItem)) {
if (bookmarkItem.stackSize <= 0) {
break;
}

int transferAmount = Math.min(bookmarkItem.stackSize, containerItem.stackSize);

moveItems(guiContainer, i, transferAmount);
bookmarkItem.stackSize -= transferAmount;

if (bookmarkItem.stackSize == 0) {
break;
}
}
}
bookmarkItem.stackSize = bookmarkSizeBackup;
}
}

private void moveItems(GuiContainer container, int fromSlot, int transferAmount) {
for (int i = 0; i < transferAmount; i++) {
int toSlot = findValidPlayerInventoryDestination(container.inventorySlots, fromSlot);
if (toSlot == -1) {
return;
}
clickSlot(container, fromSlot, 0);
clickSlot(container, toSlot, 1);
clickSlot(container, fromSlot, 0);
}
}

private void clickSlot(GuiContainer container, int slotIdx, int button) {
mc.playerController.windowClick(container.inventorySlots.windowId, slotIdx, button, 0, mc.thePlayer);
}

private int findValidPlayerInventoryDestination(Container container, int fromSlot) {
ItemStack stackToMove = container.getSlot(fromSlot).getStack();
for (int i = container.getInventory().size() - 4 * 9; i < container.getInventory().size(); i++) {
if (container.getInventory().get(i) == null) {
return i;
}
int diff = stackToMove.getMaxStackSize() - container.getInventory().get(i).stackSize;
if (container.getInventory().get(i).isItemEqual(stackToMove) && diff > 0) {
return i;
}
}
return -1;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package appeng.integration.modules.NEIHelpers;

import java.io.IOException;
import java.util.ArrayList;

import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;

import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.PacketNEIBookmark;
import codechicken.nei.api.IBookmarkContainerHandler;

public class NEIAETerminalBookmarkContainerHandler implements IBookmarkContainerHandler {

@Override
public void pullBookmarkItemsFromContainer(GuiContainer guiContainer, ArrayList<ItemStack> bookmarkItems) {
for (ItemStack bookmarkItem : bookmarkItems) {
int backupStackSize = bookmarkItem.stackSize;
int bookmarkStackSize = bookmarkItem.stackSize;
int maxStackSize = bookmarkItem.getMaxStackSize();
try {
while (bookmarkStackSize > 0) {
if (bookmarkStackSize <= maxStackSize) {
NetworkHandler.instance.sendToServer(new PacketNEIBookmark(packBookmarkItem(bookmarkItem)));
bookmarkStackSize = 0;
} else {
ItemStack splitStack = bookmarkItem.splitStack(maxStackSize);
NetworkHandler.instance.sendToServer(new PacketNEIBookmark(packBookmarkItem(splitStack)));
bookmarkStackSize -= maxStackSize;
}
}
} catch (final Exception | Error ignored) {}
bookmarkItem.stackSize = backupStackSize;
}
}

private NBTTagCompound packBookmarkItem(ItemStack bookmarkItem) throws IOException {
final NBTTagCompound comp = new NBTTagCompound();
bookmarkItem.writeToNBT(comp);
return comp;
}
}