Skip to content

Commit

Permalink
NEI Bookmark Pulling for AE2 (#372)
Browse files Browse the repository at this point in the history
* [major] implemented NEI API for bookmark pulling

* [minor] added functionality to the wireless terminal

* [minor] added functionality to the skystone chests

* added remaining guis

-better method for inventory checking

* [minor] Another rework on fitStack

* add missing imports

add forgotten import

* [minor] -sa, removed redundant code

---------

Co-authored-by: Firenoo <49818773+firenoo@users.noreply.github.com>
Co-authored-by: Martin Robertz <dream-master@gmx.net>
  • Loading branch information
3 people authored Sep 24, 2023
1 parent a423baa commit 1564929
Show file tree
Hide file tree
Showing 7 changed files with 264 additions and 2 deletions.
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
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;
}
}

0 comments on commit 1564929

Please sign in to comment.