-
Notifications
You must be signed in to change notification settings - Fork 208
/
InventoryUtil.java
180 lines (157 loc) · 6.34 KB
/
InventoryUtil.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.util;
import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.ISidedInventory;
import net.minecraft.inventory.ISidedInventoryProvider;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper;
import net.minecraftforge.items.wrapper.InvWrapper;
import net.minecraftforge.items.wrapper.SidedInvWrapper;
import org.apache.commons.lang3.tuple.Pair;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public final class InventoryUtil
{
private InventoryUtil() {}
// Methods for comparing things:
public static boolean areItemsEqual( @Nonnull ItemStack a, @Nonnull ItemStack b )
{
return a == b || ItemStack.matches( a, b );
}
public static boolean areItemsStackable( @Nonnull ItemStack a, @Nonnull ItemStack b )
{
return a == b || ItemHandlerHelper.canItemStacksStack( a, b );
}
// Methods for finding inventories:
@Nullable
public static IItemHandler getInventory( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side )
{
// Look for tile with inventory
TileEntity tileEntity = world.getBlockEntity( pos );
if( tileEntity != null )
{
LazyOptional<IItemHandler> itemHandler = tileEntity.getCapability( CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side );
if( itemHandler.isPresent() )
{
return itemHandler.orElseThrow( NullPointerException::new );
}
else if( tileEntity instanceof ISidedInventory )
{
return new SidedInvWrapper( (ISidedInventory) tileEntity, side );
}
else if( tileEntity instanceof IInventory )
{
return new InvWrapper( (IInventory) tileEntity );
}
}
BlockState block = world.getBlockState( pos );
if( block.getBlock() instanceof ISidedInventoryProvider )
{
ISidedInventory inventory = ((ISidedInventoryProvider) block.getBlock()).getContainer( block, world, pos );
return new SidedInvWrapper( inventory, side );
}
// Look for entity with inventory
Vec3d vecStart = new Vec3d(
pos.getX() + 0.5 + 0.6 * side.getStepX(),
pos.getY() + 0.5 + 0.6 * side.getStepY(),
pos.getZ() + 0.5 + 0.6 * side.getStepZ()
);
Direction dir = side.getOpposite();
Vec3d vecDir = new Vec3d(
dir.getStepX(), dir.getStepY(), dir.getStepZ()
);
Pair<Entity, Vec3d> hit = WorldUtil.rayTraceEntities( world, vecStart, vecDir, 1.1 );
if( hit != null )
{
Entity entity = hit.getKey();
if( entity instanceof IInventory )
{
return new InvWrapper( (IInventory) entity );
}
}
return null;
}
// Methods for placing into inventories:
@Nonnull
public static ItemStack storeItems( @Nonnull ItemStack itemstack, IItemHandler inventory, int begin )
{
return storeItems( itemstack, inventory, 0, inventory.getSlots(), begin );
}
@Nonnull
public static ItemStack storeItems( @Nonnull ItemStack itemstack, IItemHandler inventory )
{
return storeItems( itemstack, inventory, 0, inventory.getSlots(), 0 );
}
@Nonnull
public static ItemStack storeItems( @Nonnull ItemStack stack, IItemHandler inventory, int start, int range, int begin )
{
if( stack.isEmpty() ) return ItemStack.EMPTY;
// Inspect the slots in order and try to find empty or stackable slots
ItemStack remainder = stack.copy();
for( int i = 0; i < range; i++ )
{
int slot = start + (i + begin - start) % range;
if( remainder.isEmpty() ) break;
remainder = inventory.insertItem( slot, remainder, false );
}
return areItemsEqual( stack, remainder ) ? stack : remainder;
}
// Methods for taking out of inventories
@Nonnull
public static ItemStack takeItems( int count, IItemHandler inventory, int begin )
{
return takeItems( count, inventory, 0, inventory.getSlots(), begin );
}
@Nonnull
public static ItemStack takeItems( int count, IItemHandler inventory )
{
return takeItems( count, inventory, 0, inventory.getSlots(), 0 );
}
@Nonnull
public static ItemStack takeItems( int count, IItemHandler inventory, int start, int range, int begin )
{
// Combine multiple stacks from inventory into one if necessary
ItemStack partialStack = ItemStack.EMPTY;
for( int i = 0; i < range; i++ )
{
int slot = start + (i + begin - start) % range;
// If we've extracted all items, return
if( count <= 0 ) break;
// If this doesn't slot, abort.
ItemStack stack = inventory.getStackInSlot( slot );
if( !stack.isEmpty() && (partialStack.isEmpty() || areItemsStackable( stack, partialStack )) )
{
ItemStack extracted = inventory.extractItem( slot, count, false );
if( !extracted.isEmpty() )
{
if( partialStack.isEmpty() )
{
// If we've extracted for this first time, then limit the count to the maximum stack size.
partialStack = extracted;
count = Math.min( count, extracted.getMaxStackSize() );
}
else
{
partialStack.grow( extracted.getCount() );
}
count -= extracted.getCount();
}
}
}
return partialStack;
}
}