Skip to content
Draft
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
5 changes: 4 additions & 1 deletion src/main/java/appeng/core/sync/BasePacketHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
import appeng.core.sync.packets.NetworkStatusPacket;
import appeng.core.sync.packets.PartLeftClickPacket;
import appeng.core.sync.packets.PatternAccessTerminalPacket;
import appeng.core.sync.packets.PullItemToPlayerPacket;
import appeng.core.sync.packets.SwapSlotsPacket;
import appeng.core.sync.packets.SwitchGuisPacket;

Expand Down Expand Up @@ -110,7 +111,9 @@ public enum PacketTypes {

HOTKEY(HotkeyPacket.class, HotkeyPacket::new),

CRAFTING_JOB_STATUS(CraftingJobStatusPacket.class, CraftingJobStatusPacket::new);
CRAFTING_JOB_STATUS(CraftingJobStatusPacket.class, CraftingJobStatusPacket::new),

PULL_ITEM(PullItemToPlayerPacket.class, PullItemToPlayerPacket::new);

private final Function<FriendlyByteBuf, BasePacket> factory;

Expand Down
54 changes: 54 additions & 0 deletions src/main/java/appeng/core/sync/packets/PullItemToPlayerPacket.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package appeng.core.sync.packets;

import io.netty.buffer.Unpooled;

import net.minecraft.core.NonNullList;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.item.ItemStack;

import appeng.core.sync.BasePacket;
import appeng.menu.me.common.MEStorageMenu;

public class PullItemToPlayerPacket extends BasePacket {

private int containerId;
private NonNullList<ItemStack> stacks;
private long toPull;

public PullItemToPlayerPacket(FriendlyByteBuf stream) {
containerId = stream.readInt();
stacks = NonNullList.withSize(stream.readInt(), ItemStack.EMPTY);
for (int i = 0; i < stacks.size(); i++) {
stacks.set(i, stream.readItem());
}
toPull = stream.readVarLong();
}

public PullItemToPlayerPacket(int containerId, NonNullList<ItemStack> stacks, long toPull) {
var data = new FriendlyByteBuf(Unpooled.buffer());

data.writeInt(this.getPacketID());

data.writeInt(containerId);
data.writeInt(stacks.size());
for (ItemStack stack : stacks) {
data.writeItem(stack);
}
data.writeVarLong(toPull);

configureWrite(data);
}

@Override
public void serverPacketData(ServerPlayer player) {
if (player.containerMenu instanceof MEStorageMenu aeMenu) {
if (player.containerMenu.containerId != containerId) {
return;
}

aeMenu.transferMatchingStacksToPlayer(stacks, toPull);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ public void register(EmiRegistry registry) {
registry.addGenericExclusionArea(new EmiAeBaseScreenExclusionZones());
registry.addGenericStackProvider(new EmiAeBaseScreenStackProvider());
registry.addGenericDragDropHandler(new EmiAeBaseScreenDragDropHandler());
registry.addGenericStackPuller(new EmiAeBaseScreenStackPuller());

// Additional Workstations
registerWorkstations(registry);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package appeng.integration.modules.emi;

import java.util.List;

import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.PullItemToPlayerPacket;
import appeng.menu.me.common.MEStorageMenu;
import dev.emi.emi.api.EmiStackPuller;
import net.minecraft.core.NonNullList;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.network.PacketDistributor;

public class EmiAeBaseScreenStackPuller implements EmiStackPuller<AbstractContainerMenu> {

@Override
public boolean pullStack(AbstractContainerMenu menu, List<ItemStack> stacks, long toPull) {
if (!(menu instanceof MEStorageMenu aeMenu)) {
return false;
}

NonNullList<ItemStack> nonNullStacks = NonNullList.withSize(stacks.size(), ItemStack.EMPTY);
for (int i = 0; i < stacks.size(); i++) {
nonNullStacks.set(i, stacks.get(i));
}

NetworkHandler.instance()
.sendToServer(new PullItemToPlayerPacket(menu.containerId, nonNullStacks, toPull));

return true;
}

}
30 changes: 30 additions & 0 deletions src/main/java/appeng/menu/AEBaseMenu.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import appeng.api.networking.security.IActionHost;
import appeng.api.networking.security.IActionSource;
import appeng.api.parts.IPart;
import appeng.api.stacks.AEItemKey;
import appeng.api.stacks.AEKey;
import appeng.api.stacks.GenericStack;
import appeng.api.upgrades.IUpgradeInventory;
Expand Down Expand Up @@ -525,6 +526,35 @@ private boolean x(Slot clickSlot, ItemStack tis, Slot d) {
return false;
}

protected List<Slot> getQuickMoveDestinationSlots(ItemStack stackToMove) {
// Find potential destination slots
var destinationSlots = new ArrayList<Slot>();
for (var candidateSlot : this.slots) {
if (candidateSlot.container instanceof Inventory && candidateSlot.mayPlace(stackToMove)) {
destinationSlots.add(candidateSlot);
}
}

// Sort such that we fill existing stacks first where possible
destinationSlots.sort((a, b) -> Boolean.compare(b.hasItem(), a.hasItem()));
return destinationSlots;
}

protected int getPlaceableAmount(Slot s, AEItemKey what) {
if (!s.mayPlace(what.toStack())) {
return 0;
}

var currentItem = s.getItem();
if (currentItem.isEmpty()) {
return s.getMaxStackSize(what.getReadOnlyStack());
} else if (what.matches(currentItem)) {
return Math.max(0, s.getMaxStackSize(currentItem) - currentItem.getCount());
} else {
return 0;
}
}

@Override
public boolean stillValid(Player PlayerEntity) {
if (this.isValidMenu()) {
Expand Down
37 changes: 37 additions & 0 deletions src/main/java/appeng/menu/me/common/MEStorageMenu.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

import org.jetbrains.annotations.Nullable;

import net.minecraft.core.NonNullList;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.MenuType;
Expand Down Expand Up @@ -668,6 +669,42 @@ private boolean moveOneStackToPlayer(AEItemKey stack) {
return true;
}

public void transferMatchingStacksToPlayer(NonNullList<ItemStack> stacks, long toPull) {
for (ItemStack stack : stacks) {
AEItemKey key = AEItemKey.of(stack);

long potentialAmount = storage.extract(key, toPull, Actionable.SIMULATE, getActionSource());
if (potentialAmount <= 0) {
continue;
}

var destinationSlots = getQuickMoveDestinationSlots(key.toStack());

for (var destinationSlot : destinationSlots) {
var amount = Math.min(toPull, getPlaceableAmount(destinationSlot, key));
if (amount <= 0) {
continue;
}

var extracted = StorageHelper.poweredExtraction(powerSource, storage, key, amount, getActionSource());
if (extracted == 0) {
break; // No items available, try next matching type
}

var currentItem = destinationSlot.getItem();
if (!currentItem.isEmpty()) {
destinationSlot.setByPlayer(currentItem.copyWithCount(currentItem.getCount() + (int) extracted));
} else {
destinationSlot.setByPlayer(key.toStack((int) extracted));
}

toPull -= extracted;
}

if (toPull <= 0) return;
}
}

@Nullable
protected final AEKey getStackBySerial(long serial) {
return updateHelper.getBySerial(serial);
Expand Down