Skip to content

Commit 8dd5717

Browse files
authored
Pipe Config Card to extract blocks from items containing items (such as Banks from Bank Storage) (#1022)
Also fix some bugs in `TransferHelper#extractMatching`.
1 parent 2a8e49b commit 8dd5717

File tree

3 files changed

+59
-21
lines changed

3 files changed

+59
-21
lines changed

src/main/java/aztech/modern_industrialization/pipes/impl/PipeBlockEntity.java

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@
6666
import net.minecraft.world.phys.shapes.VoxelShape;
6767
import net.neoforged.neoforge.client.model.data.ModelData;
6868
import net.neoforged.neoforge.client.model.data.ModelProperty;
69-
import net.neoforged.neoforge.items.wrapper.PlayerInvWrapper;
7069
import org.jetbrains.annotations.Nullable;
7170

7271
/**
@@ -253,7 +252,11 @@ public ItemStack getCamouflageStack() {
253252
/**
254253
* Set the camouflage directly. The camouflage block should be consumed from the player before calling this.
255254
*/
256-
private void setCamouflage(Player player, @Nullable BlockState newCamouflage) {
255+
private void setCamouflage(@Nullable BlockState newCamouflage) {
256+
if (level.isClientSide) {
257+
throw new IllegalStateException("Cannot call setCamouflage on the client");
258+
}
259+
257260
boolean hadCamouflage = hasCamouflage();
258261

259262
if (camouflage != null) {
@@ -267,16 +270,14 @@ private void setCamouflage(Player player, @Nullable BlockState newCamouflage) {
267270
if (newCamouflage == null) {
268271
var group = camouflage.getSoundType();
269272
var sound = group.getBreakSound();
270-
level.playSound(player, worldPosition, sound, SoundSource.BLOCKS, (group.getVolume() + 1.0F) / 4.0F, group.getPitch() * 0.8F);
273+
level.playSound(null, worldPosition, sound, SoundSource.BLOCKS, (group.getVolume() + 1.0F) / 4.0F, group.getPitch() * 0.8F);
271274
}
272275

273276
// Remove camouflage
274277
camouflage = null;
275278
setChanged();
276-
if (!level.isClientSide()) {
277-
sync();
278-
rebuildCollisionShape();
279-
}
279+
sync();
280+
rebuildCollisionShape();
280281
}
281282

282283
camouflage = newCamouflage;
@@ -285,13 +286,11 @@ private void setCamouflage(Player player, @Nullable BlockState newCamouflage) {
285286
// Play a cool sound
286287
var group = newCamouflage.getSoundType();
287288
var sound = group.getPlaceSound();
288-
level.playSound(player, worldPosition, sound, SoundSource.BLOCKS, (group.getVolume() + 1.0F) / 4.0F, group.getPitch() * 0.8F);
289+
level.playSound(null, worldPosition, sound, SoundSource.BLOCKS, (group.getVolume() + 1.0F) / 4.0F, group.getPitch() * 0.8F);
289290

290291
setChanged();
291-
if (!level.isClientSide()) {
292-
sync();
293-
rebuildCollisionShape();
294-
}
292+
sync();
293+
rebuildCollisionShape();
295294
}
296295

297296
if (hadCamouflage != hasCamouflage()) {
@@ -310,7 +309,9 @@ public boolean tryRemoveCamouflage(Player player, InteractionHand hand) {
310309
return false;
311310
}
312311

313-
setCamouflage(player, null);
312+
if (!player.level().isClientSide) {
313+
setCamouflage(null);
314+
}
314315

315316
return true;
316317
}
@@ -340,11 +341,16 @@ public boolean tryApplyCamouflage(Player player, InteractionHand hand) {
340341
return true;
341342
}
342343

344+
// Item capabilities shouldn't be messed with (and in some cases cannot - leading to inconsistent behavior) on the client side
345+
if (player.level().isClientSide) {
346+
return true;
347+
}
348+
343349
boolean itemChanged = camouflage == null || newCamouflage.getBlock() != camouflage.getBlock();
344350

345351
if (!player.getAbilities().instabuild && itemChanged) {
346352
var itemToUse = newCamouflage.getBlock().asItem();
347-
var extracted = TransferHelper.extractMatching(new PlayerInvWrapper(player.getInventory()), s -> s.is(itemToUse), 1);
353+
var extracted = TransferHelper.extractMatching(player.getInventory(), s -> s.is(itemToUse), 1, true);
348354

349355
if (extracted.isEmpty()) {
350356
player.displayClientMessage(MITooltips.line(MIText.ConfigCardNoCamouflageInInventory)
@@ -353,7 +359,7 @@ public boolean tryApplyCamouflage(Player player, InteractionHand hand) {
353359
}
354360
}
355361

356-
setCamouflage(player, newCamouflage);
362+
setCamouflage(newCamouflage);
357363
return true;
358364
}
359365

src/main/java/aztech/modern_industrialization/pipes/item/ItemNetworkNode.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@
6161
import net.neoforged.neoforge.capabilities.BlockCapabilityCache;
6262
import net.neoforged.neoforge.capabilities.Capabilities;
6363
import net.neoforged.neoforge.items.IItemHandler;
64-
import net.neoforged.neoforge.items.wrapper.PlayerInvWrapper;
6564
import org.jetbrains.annotations.Nullable;
6665

6766
public class ItemNetworkNode extends PipeNetworkNode {
@@ -371,7 +370,7 @@ void applyConfig(PipeBlockEntity pipe, @Nullable SavedItemPipeConfig config, Pla
371370
}
372371

373372
private int fetchItems(Player player, ItemVariant what, int maxAmount) {
374-
return TransferHelper.extractMatching(new PlayerInvWrapper(player.getInventory()), what::matches, maxAmount).getCount();
373+
return TransferHelper.extractMatching(player.getInventory(), what::matches, maxAmount, false).getCount();
375374
}
376375

377376
private class ScreenHandlerFactory implements IPipeMenuProvider {

src/main/java/aztech/modern_industrialization/util/TransferHelper.java

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,12 @@
2525

2626
import aztech.modern_industrialization.MI;
2727
import java.util.function.Predicate;
28+
import net.minecraft.world.entity.player.Inventory;
2829
import net.minecraft.world.item.ItemStack;
30+
import net.neoforged.neoforge.capabilities.Capabilities;
2931
import net.neoforged.neoforge.items.IItemHandler;
3032
import net.neoforged.neoforge.items.ItemHandlerHelper;
33+
import net.neoforged.neoforge.items.wrapper.PlayerInvWrapper;
3134

3235
public class TransferHelper {
3336
public static void moveAll(IItemHandler src, IItemHandler target, boolean stackInTarget) {
@@ -67,6 +70,37 @@ public static void moveAll(IItemHandler src, IItemHandler target, boolean stackI
6770
}
6871
}
6972

73+
public static ItemStack extractMatching(Inventory inventory, Predicate<ItemStack> predicate, int maxAmount, boolean containers) {
74+
int srcSlots = inventory.getContainerSize();
75+
76+
var ret = extractMatching(new PlayerInvWrapper(inventory), predicate, maxAmount);
77+
78+
// Try to extract from item containing items
79+
if (containers) {
80+
if (!ret.isEmpty()) {
81+
final var finalRet = ret;
82+
predicate = other -> ItemStack.isSameItemSameComponents(finalRet, other);
83+
}
84+
for (int slot = 0; slot < srcSlots && maxAmount > ret.getCount(); ++slot) {
85+
var stack = inventory.getItem(slot);
86+
if (stack.getCount() != 1) {
87+
continue;
88+
}
89+
var capability = stack.getCapability(Capabilities.ItemHandler.ITEM);
90+
if (capability != null) {
91+
var extracted = extractMatching(capability, predicate, maxAmount - ret.getCount());
92+
if (ret.isEmpty()) {
93+
ret = extracted;
94+
} else {
95+
ret.grow(extracted.getCount());
96+
}
97+
}
98+
}
99+
}
100+
101+
return ret;
102+
}
103+
70104
public static ItemStack extractMatching(IItemHandler src, Predicate<ItemStack> predicate, int maxAmount) {
71105
int srcSlots = src.getSlots();
72106

@@ -84,11 +118,10 @@ public static ItemStack extractMatching(IItemHandler src, Predicate<ItemStack> p
84118
}
85119

86120
// Try to extract more
87-
++slot;
88-
for (; slot < srcSlots && maxAmount < ret.getCount(); ++slot) {
121+
for (; slot < srcSlots && maxAmount > ret.getCount(); ++slot) {
89122
var stack = src.getStackInSlot(slot);
90-
if (ItemStack.matches(stack, ret)) {
91-
var extracted = src.extractItem(slot, maxAmount - ret.getCount(), true);
123+
if (ItemStack.isSameItemSameComponents(stack, ret)) {
124+
var extracted = src.extractItem(slot, maxAmount - ret.getCount(), false);
92125
ret.grow(extracted.getCount());
93126
}
94127
}

0 commit comments

Comments
 (0)