diff --git a/.github/workflows/main-ci.yml b/.github/workflows/main-ci.yml index 0dbdaf69c..cf74d810a 100644 --- a/.github/workflows/main-ci.yml +++ b/.github/workflows/main-ci.yml @@ -31,17 +31,3 @@ jobs: with: name: cc-restiched path: build/libs - - - name: Upload Coverage - run: bash <(curl -s https://codecov.io/bash) - continue-on-error: true - - - name: Lint Lua code - run: | - test -d bin || mkdir bin - test -f bin/illuaminate || wget -q -Obin/illuaminate https://squiddev.cc/illuaminate/linux-x86-64/illuaminate - chmod +x bin/illuaminate - bin/illuaminate lint - - - name: Check whitespace - run: python3 tools/check-lines.py diff --git a/README.md b/README.md index c13963b4d..243ffc5ad 100644 --- a/README.md +++ b/README.md @@ -43,8 +43,8 @@ If you need help getting started with CC: Tweaked, want to show off your latest Main Known issue * Mods that add blocks that can be used as peripherals for CC:T On forge, dont work with CC:R. * This is because of the differences between forge and fabric, and that mod devs, to my knowledge have not agreed upon a standard method in which to implement cross compatibility between mods, -* Storage Peripherals throw a java "StackOverflowError" when using `pushItems()`, - * Work around, you are probably using `pushItems(chest, 1)` or simular. please use `pushItems(chest, 1, nil, 1)`. +* [Fixed (d10f297c): please report if bug persists]
~~Storage Peripherals throw a java "StackOverflowError" when using `pushItems()`,~~ + * ~~Work around, you are probably using `pushItems(chest, 1)` or similar. please use `pushItems(chest, 1, nil, 1)`.~~ ## Known Working mods that add Peripherals * Please let me know of other mods that work with this one diff --git a/src/main/java/dan200/computercraft/client/render/ModelTransformer.java b/src/main/java/dan200/computercraft/client/render/ModelTransformer.java index 5ff96bdd5..b8a766e0a 100644 --- a/src/main/java/dan200/computercraft/client/render/ModelTransformer.java +++ b/src/main/java/dan200/computercraft/client/render/ModelTransformer.java @@ -14,8 +14,8 @@ import net.minecraft.client.render.VertexFormatElement; import net.minecraft.client.render.VertexFormats; import net.minecraft.client.render.model.BakedQuad; +import net.minecraft.client.util.math.Vector4f; import net.minecraft.util.math.Matrix4f; -import net.minecraft.util.math.Quaternion; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; @@ -50,41 +50,31 @@ public static void transformQuadsTo(VertexFormat format, List output, } private static BakedQuad doTransformQuad(VertexFormat format, BakedQuad quad, Matrix4f transform) { - int[] vertexData = quad.getVertexData() - .clone(); - int offset = 0; + int[] vertexData = quad.getVertexData().clone(); BakedQuad copy = new BakedQuad(vertexData, -1, quad.getFace(), ((BakedQuadAccess)quad).getSprite(), true); - for (int i = 0; i < format.getElements() - .size(); ++i) // For each vertex element - { - VertexFormatElement element = format.getElements() - .get(i); - if (element.getType() == VertexFormatElement.Type.POSITION && element.getFormat() == VertexFormatElement.Format.FLOAT && element.getSize() == 3) // When we find a position - // element + + int offsetBytes = 0; + for (int v = 0; v < 4; ++v) { + for (VertexFormatElement element : format.getElements()) // For each vertex element { - for (int j = 0; j < 4; ++j) // For each corner of the quad + int start = offsetBytes / Integer.BYTES; + if (element.getType() == VertexFormatElement.Type.POSITION && element.getFormat() == VertexFormatElement.Format.FLOAT) // When we find a position element { - int start = offset + j * format.getVertexSize(); - if ((start % 4) == 0) { - start = start / 4; - - // Extract the position - Quaternion pos = new Quaternion(Float.intBitsToFloat(vertexData[start]), - Float.intBitsToFloat(vertexData[start + 1]), - Float.intBitsToFloat(vertexData[start + 2]), - 1); + Vector4f pos = new Vector4f(Float.intBitsToFloat(vertexData[start]), + Float.intBitsToFloat(vertexData[start+1]), + Float.intBitsToFloat(vertexData[start+2]), + 1); - // Transform the position - transform.multiply(pos); + // Transform the position + pos.transform(transform); - // Insert the position - vertexData[start] = Float.floatToRawIntBits(pos.getX()); - vertexData[start + 1] = Float.floatToRawIntBits(pos.getY()); - vertexData[start + 2] = Float.floatToRawIntBits(pos.getZ()); - } + // Insert the position + vertexData[start] = Float.floatToRawIntBits(pos.getX()); + vertexData[start+1] = Float.floatToRawIntBits(pos.getY()); + vertexData[start+2] = Float.floatToRawIntBits(pos.getZ()); } + offsetBytes += element.getSize(); } - offset += element.getSize(); } return copy; } diff --git a/src/main/java/dan200/computercraft/client/render/TurtleSmartItemModel.java b/src/main/java/dan200/computercraft/client/render/TurtleSmartItemModel.java index 1f31e18dc..7465a5215 100644 --- a/src/main/java/dan200/computercraft/client/render/TurtleSmartItemModel.java +++ b/src/main/java/dan200/computercraft/client/render/TurtleSmartItemModel.java @@ -78,9 +78,10 @@ public BakedModel apply(@Nonnull BakedModel originalModel, @Nonnull ItemStack st Identifier overlay = turtle.getOverlay(stack); boolean christmas = HolidayUtil.getCurrentHoliday() == Holiday.CHRISTMAS; String label = turtle.getLabel(stack); - boolean flip = label != null && (label.equals("Dinnerbone") || label.equals("Grumm")); - // TODO Make TurtleTool render for turtle items again. - TurtleModelCombination combo = new TurtleModelCombination(colour != -1, !(leftUpgrade instanceof TurtleTool) ? leftUpgrade : null, !(rightUpgrade instanceof TurtleTool) ? rightUpgrade : null, overlay, christmas, flip); + // TODO make upside down turtle items render properly (currently inivisible) + //boolean flip = label != null && (label.equals("Dinnerbone") || label.equals("Grumm")); + boolean flip = false; + TurtleModelCombination combo = new TurtleModelCombination(colour != -1, leftUpgrade, rightUpgrade, overlay, christmas, flip); BakedModel model = TurtleSmartItemModel.this.m_cachedModels.get(combo); if (model == null) { diff --git a/src/main/java/dan200/computercraft/shared/peripheral/generic/GenericPeripheralProvider.java b/src/main/java/dan200/computercraft/shared/peripheral/generic/GenericPeripheralProvider.java index b37104fe5..d4b3e0b16 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/generic/GenericPeripheralProvider.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/generic/GenericPeripheralProvider.java @@ -28,7 +28,6 @@ public static IPeripheral getPeripheral( @Nonnull World world, @Nonnull BlockPos ArrayList saturated = new ArrayList<>( 0 ); - // This seems to add inventory methods, how??? List> tileMethods = PeripheralMethod.GENERATOR.getMethods( tile.getClass() ); if( !tileMethods.isEmpty() ) addSaturated( saturated, tile, tileMethods ); diff --git a/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/InventoryMethods.java b/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/InventoryMethods.java index 48ea969fb..149a89f0a 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/InventoryMethods.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/InventoryMethods.java @@ -13,6 +13,8 @@ import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.core.asm.GenericSource; import dan200.computercraft.shared.peripheral.generic.data.ItemData; +import dan200.computercraft.shared.util.InventoryUtil; +import dan200.computercraft.shared.util.ItemStorage; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.ChestBlock; @@ -60,10 +62,7 @@ public Identifier id() @LuaFunction( mainThread = true ) public static int size( Inventory inventory ) { - // Get appropriate inventory for source peripheral - inventory = extractHandler(inventory); - - return inventory.size(); + return extractHandler(inventory).size(); } /** @@ -73,9 +72,13 @@ public static int size( Inventory inventory ) * @return The name of this inventory, or {@code nil} if not present. */ @LuaFunction( mainThread = true ) - public static String name( Nameable inventory ) + public static String name( Inventory inventory ) { - return inventory.hasCustomName() ? inventory.getName().asString() : null; + if ( inventory instanceof Nameable ) { + Nameable i = (Nameable)inventory; + return i.hasCustomName() ? i.getName().asString() : null; + } + return null; } /** @@ -95,14 +98,13 @@ public static String name( Nameable inventory ) @LuaFunction( mainThread = true ) public static Map> list( Inventory inventory ) { - // Get appropriate inventory for source peripheral - inventory = extractHandler(inventory); + ItemStorage itemStorage = extractHandler(inventory); Map> result = new HashMap<>(); - int size = inventory.size(); + int size = itemStorage.size(); for( int i = 0; i < size; i++ ) { - ItemStack stack = inventory.getStack( i ); + ItemStack stack = itemStorage.getStack( i ); if( !stack.isEmpty() ) result.put( i + 1, ItemData.fillBasic( new HashMap<>( 4 ), stack ) ); } @@ -122,12 +124,11 @@ public static String name( Nameable inventory ) @LuaFunction( mainThread = true ) public static Map getItemDetail( Inventory inventory, int slot ) throws LuaException { - // Get appropriate inventory - inventory = extractHandler(inventory); + ItemStorage itemStorage = extractHandler(inventory); - assertBetween( slot, 1, inventory.size(), "Slot out of range (%s)" ); + assertBetween( slot, 1, itemStorage.size(), "Slot out of range (%s)" ); - ItemStack stack = inventory.getStack( slot - 1 ); + ItemStack stack = itemStorage.getStack( slot - 1 ); return stack.isEmpty() ? null : ItemData.fill( new HashMap<>(), stack ); } @@ -162,23 +163,22 @@ public static int pushItems( String toName, int fromSlot, Optional limit, Optional toSlot ) throws LuaException { - // Get appropriate inventory for source peripheral - from = extractHandler(from); + ItemStorage fromStorage = extractHandler( from ); // Find location to transfer to IPeripheral location = computer.getAvailablePeripheral( toName ); if( location == null ) throw new LuaException( "Target '" + toName + "' does not exist" ); - Inventory to = extractHandler( location.getTarget() ); - if( to == null ) throw new LuaException( "Target '" + toName + "' is not an inventory" ); + ItemStorage toStorage = extractHandler( location.getTarget() ); + if( toStorage == null ) throw new LuaException( "Target '" + toName + "' is not an inventory" ); // Validate slots int actualLimit = limit.orElse( Integer.MAX_VALUE ); - assertBetween( fromSlot, 1, from.size(), "From slot out of range (%s)" ); - if( toSlot.isPresent() ) assertBetween( toSlot.get(), 1, to.size(), "To slot out of range (%s)" ); + assertBetween( fromSlot, 1, fromStorage.size(), "From slot out of range (%s)" ); + if( toSlot.isPresent() ) assertBetween( toSlot.get(), 1, toStorage.size(), "To slot out of range (%s)" ); if( actualLimit <= 0 ) return 0; - return moveItem( from, fromSlot - 1, to, toSlot.orElse( 0 ) - 1, actualLimit ); + return moveItem( fromStorage, fromSlot - 1, toStorage, toSlot.orElse( 0 ) - 1, actualLimit ); } /** @@ -213,55 +213,36 @@ public static int pullItems( ) throws LuaException { // Get appropriate inventory for source peripheral - to = extractHandler(to); + ItemStorage toStorage = extractHandler( to ); // Find location to transfer to IPeripheral location = computer.getAvailablePeripheral( fromName ); if( location == null ) throw new LuaException( "Source '" + fromName + "' does not exist" ); - Inventory from = extractHandler( location.getTarget() ); - if( from == null ) throw new LuaException( "Source '" + fromName + "' is not an inventory" ); + ItemStorage fromStorage = extractHandler( location.getTarget() ); + if( fromStorage == null ) throw new LuaException( "Source '" + fromName + "' is not an inventory" ); // Validate slots int actualLimit = limit.orElse( Integer.MAX_VALUE ); - assertBetween( fromSlot, 1, from.size(), "From slot out of range (%s)" ); - if( toSlot.isPresent() ) assertBetween( toSlot.get(), 1, to.size(), "To slot out of range (%s)" ); + assertBetween( fromSlot, 1, fromStorage.size(), "From slot out of range (%s)" ); + if( toSlot.isPresent() ) assertBetween( toSlot.get(), 1, toStorage.size(), "To slot out of range (%s)" ); if( actualLimit <= 0 ) return 0; - return moveItem( from, fromSlot - 1, to, toSlot.orElse( 0 ) - 1, actualLimit ); + return moveItem( fromStorage, fromSlot - 1, toStorage, toSlot.orElse( 0 ) - 1, actualLimit ); } - /** - * Extracts the most appropriate inventory from the object - * e.g., the correct inventory for a double chest or a sided inventory. - * - * @param object The handler to move from. - * @return The appropriate Inventory. - */ @Nullable - private static Inventory extractHandler( @Nullable Object object ) + private static ItemStorage extractHandler( @Nullable Object object ) { - Inventory inventory = null; - - if (object instanceof BlockEntity ) { - BlockEntity blockEntity = (BlockEntity) object; - World world = blockEntity.getWorld(); - BlockPos blockPos = blockEntity.getPos(); - BlockState blockState = world.getBlockState(blockPos); - Block block = blockState.getBlock(); - - if (block instanceof InventoryProvider) { - inventory = ((InventoryProvider)block).getInventory(blockState, world, blockPos); - } else if (blockEntity instanceof Inventory) { - inventory = (Inventory)blockEntity; - if (inventory instanceof ChestBlockEntity && block instanceof ChestBlock) { - inventory = ChestBlock.getInventory((ChestBlock) block, blockState, world, blockPos, true); - } + if ( object instanceof BlockEntity ) { + Inventory inventory = InventoryUtil.getInventory((BlockEntity) object); + if ( inventory != null ) { + return ItemStorage.wrap(inventory); } } - return inventory; + return null; } /** @@ -274,109 +255,36 @@ private static Inventory extractHandler( @Nullable Object object ) * @param limit The max number to move. {@link Integer#MAX_VALUE} for no limit. * @return The number of items moved. */ - private static int moveItem( Inventory from, int fromSlot, Inventory to, int toSlot, final int limit ) + private static int moveItem( ItemStorage from, int fromSlot, ItemStorage to, int toSlot, final int limit ) { - - /* ORIGINAL FORGE CODE - // See how much we can get out of this slot - // ItemStack extracted = from.extractItem( fromSlot, limit, true ); - if( extracted.isEmpty() ) return 0; - - // Limit the amount to extract - int extractCount = Math.min( extracted.getCount(), limit ); - extracted.setCount( extractCount ); - - // ItemStack remainder = toSlot < 0 ? bItemHandlerHelper.insertItem( to, extracted, false ) : to.insertItem( toSlot, extracted, false ); - int inserted = remainder.isEmpty() ? extractCount : extractCount - remainder.getCount(); - if( inserted <= 0 ) return 0; - - // Remove the item from the original inventory. Technically this could fail, but there's little we can do - // about that. - from.extractItem( fromSlot, inserted, false ); - */ - - // Vanilla minecraft inventory manipulation code - Boolean recurse = false; - ItemStack source = from.getStack( fromSlot ); - int count = 0; - - // If target slot was selected, only push items to that slot. - if (toSlot >= 0) { - int space = amountStackCanAddFrom(to.getStack(toSlot), source, to); - if (space == 0) return 0; - count = space; - } - // If target slot not selected, push items where they will fit, possibly - // across slots (by recurring on this method). - else if (toSlot < 0) { - recurse = true; - int[] result = getFirstValidSlotAndSpace(source, to); - toSlot = result[0]; - if(toSlot < 0) return 0; - count = result[1]; + // Moving nothing is easy + if (limit == 0) { + return 0; } - // Respect slot restrictions - if (!to.isValid(toSlot, source)) { return 0; } - - // Compare count available in target ItemStack to limit specified. - count = Math.min(count, limit); - if (count == 0) return 0; + // Get stack to move + ItemStack stack = InventoryUtil.takeItems(limit, from, fromSlot, 1, fromSlot); + if (stack.isEmpty()) { + return 0; + } + int stackCount = stack.getCount(); - // Mutate destination and source ItemStack - ItemStack destination = to.getStack(toSlot); - if (destination.isEmpty()) { - ItemStack newStack = source.copy(); - newStack.setCount(count); - to.setStack(toSlot, newStack); + // Move items in + ItemStack remainder; + if (toSlot < 0) { + remainder = InventoryUtil.storeItems(stack, to); } else { - destination.increment(count); + remainder = InventoryUtil.storeItems(stack, to, toSlot, 1, toSlot); } - source.decrement(count); - if (source.isEmpty()) from.setStack(fromSlot, ItemStack.EMPTY); - - to.markDirty(); - from.markDirty(); - - // Recurse if no explicit destination slot and more items exist in source slot - // and limit hasn't been reached. Else, return items moved. - if (recurse && !source.isEmpty()) return count + moveItem(from, fromSlot, to, -1, limit - count); - return count; - } - // Maybe there is a nicer existing way to do this in the minecraft codebase. I couldn't find it. - private static int[] getFirstValidSlotAndSpace(ItemStack fromStack, Inventory inventory) { - for (int i = 0; i < inventory.size(); i++) { - ItemStack stack = inventory.getStack(i); - int space = amountStackCanAddFrom(stack, fromStack, inventory); - if (space > 0) { - return new int[]{i, space}; - } - } - return new int[]{-1, 0}; - } + // Calculate items moved + int count = stackCount - remainder.getCount(); - private static int amountStackCanAddFrom(ItemStack existingStack, ItemStack fromStack, Inventory inventory) { - if (fromStack.isEmpty()) { - return 0; + if (!remainder.isEmpty()) { + // Put the remainder back + InventoryUtil.storeItems(remainder, from, fromSlot, 1, fromSlot); } - else if (existingStack.isEmpty()) { - return Math.min(Math.min(existingStack.getMaxCount(), - inventory.getMaxCountPerStack()), - fromStack.getCount()); - } - else if (InventoryMethods.areItemsEqual(existingStack, fromStack) && - existingStack.isStackable() && - existingStack.getCount() < existingStack.getMaxCount() && - existingStack.getCount() < inventory.getMaxCountPerStack()) { - int stackSpace = existingStack.getMaxCount() - existingStack.getCount(); - int invSpace = inventory.getMaxCountPerStack() - existingStack.getCount(); - return Math.min(Math.min(stackSpace, invSpace), fromStack.getCount()); - } - return 0; - } - private static boolean areItemsEqual(ItemStack stack1, ItemStack stack2) { - return stack1.getItem() == stack2.getItem() && ItemStack.areTagsEqual(stack1, stack2); + return count; } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlaceCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlaceCommand.java index 2f759f242..d30264751 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlaceCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlaceCommand.java @@ -22,6 +22,7 @@ import dan200.computercraft.shared.util.DropConsumer; import dan200.computercraft.shared.util.InventoryUtil; import dan200.computercraft.shared.util.WorldUtil; +import net.minecraft.item.*; import org.apache.commons.lang3.tuple.Pair; import net.minecraft.block.BlockState; @@ -29,16 +30,6 @@ import net.minecraft.block.entity.SignBlockEntity; import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; -import net.minecraft.item.BlockItem; -import net.minecraft.item.BoatItem; -import net.minecraft.item.BucketItem; -import net.minecraft.item.GlassBottleItem; -import net.minecraft.item.Item; -import net.minecraft.item.ItemPlacementContext; -import net.minecraft.item.ItemStack; -import net.minecraft.item.ItemUsageContext; -import net.minecraft.item.LilyPadItem; -import net.minecraft.item.SignItem; import net.minecraft.text.LiteralText; import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; @@ -224,27 +215,18 @@ private static ItemStack deployOnEntity(@Nonnull ItemStack stack, final ITurtleA // Place on the entity boolean placed = false; ActionResult cancelResult = hitEntity.interactAt(turtlePlayer, hitPos, Hand.MAIN_HAND); - if (cancelResult == null) { - cancelResult = hitEntity.interactAt(turtlePlayer, hitPos, Hand.MAIN_HAND); - } if (cancelResult != null && cancelResult.isAccepted()) { placed = true; - } else if (hitEntity instanceof LivingEntity) { - // See EntityPlayer.interactOn - cancelResult = stackCopy.useOnEntity(turtlePlayer, (LivingEntity) hitEntity, Hand.MAIN_HAND); + } + else { + cancelResult = hitEntity.interact(turtlePlayer, Hand.MAIN_HAND); if (cancelResult != null && cancelResult.isAccepted()) { placed = true; - } else if (cancelResult == null) { - if (hitEntity.interact(turtlePlayer, Hand.MAIN_HAND) == ActionResult.CONSUME) { - placed = true; - } else { - placed = stackCopy.useOnEntity(turtlePlayer, (LivingEntity) hitEntity, Hand.MAIN_HAND) - .isAccepted(); - if (placed) { - turtlePlayer.loadInventory(stackCopy); - } - } + } + else if (hitEntity instanceof LivingEntity) { + placed = stackCopy.useOnEntity(turtlePlayer, (LivingEntity) hitEntity, Hand.MAIN_HAND).isAccepted(); + if (placed) turtlePlayer.loadInventory(stackCopy); } } @@ -304,11 +286,9 @@ private static ItemStack deployOnBlock(@Nonnull ItemStack stack, ITurtleAccess t BlockEntity existingTile = turtle.getWorld() .getBlockEntity(position); - if (placementContext.canPlace()) { - if (stackCopy.useOnBlock(context) == ActionResult.SUCCESS) { - placed = true; - turtlePlayer.loadInventory(stackCopy); - } + if (stackCopy.useOnBlock(context).isAccepted()) { + placed = true; + turtlePlayer.loadInventory(stackCopy); } if (!placed && (item instanceof BucketItem || item instanceof BoatItem || item instanceof LilyPadItem || item instanceof GlassBottleItem)) { diff --git a/src/main/java/dan200/computercraft/shared/util/InventoryUtil.java b/src/main/java/dan200/computercraft/shared/util/InventoryUtil.java index f1477363b..9eac0209e 100644 --- a/src/main/java/dan200/computercraft/shared/util/InventoryUtil.java +++ b/src/main/java/dan200/computercraft/shared/util/InventoryUtil.java @@ -8,6 +8,11 @@ import javax.annotation.Nonnull; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.ChestBlock; +import net.minecraft.block.InventoryProvider; +import net.minecraft.block.entity.ChestBlockEntity; import org.apache.commons.lang3.tuple.Pair; import net.minecraft.block.entity.BlockEntity; @@ -33,9 +38,20 @@ public static Inventory getInventory(World world, BlockPos pos, Direction side) // Look for tile with inventory int y = pos.getY(); if (y >= 0 && y < world.getHeight()) { - BlockEntity tileEntity = world.getBlockEntity(pos); - if (tileEntity instanceof Inventory) { - return (Inventory) tileEntity; + // Check if block is InventoryProvider + BlockState blockState = world.getBlockState(pos); + Block block = blockState.getBlock(); + if (block instanceof InventoryProvider) { + return ((InventoryProvider)block).getInventory(blockState, world, pos); + } + // Check if block is BlockEntity w/ Inventory + if (block.hasBlockEntity()) { + BlockEntity tileEntity = world.getBlockEntity(pos); + + Inventory inventory = getInventory(tileEntity); + if (inventory != null) { + return inventory; + } } } @@ -55,6 +71,23 @@ public static Inventory getInventory(World world, BlockPos pos, Direction side) return null; } + public static Inventory getInventory(BlockEntity tileEntity) { + World world = tileEntity.getWorld(); + BlockPos pos = tileEntity.getPos(); + BlockState blockState = world.getBlockState(pos); + Block block = blockState.getBlock(); + + if (tileEntity instanceof Inventory) { + Inventory inventory = (Inventory)tileEntity; + if (inventory instanceof ChestBlockEntity && block instanceof ChestBlock) { + return ChestBlock.getInventory((ChestBlock) block, blockState, world, pos, true); + } + return inventory; + } + + return null; + } + @Nonnull public static ItemStack storeItems(@Nonnull ItemStack itemstack, ItemStorage inventory, int begin) { return storeItems(itemstack, inventory, 0, inventory.size(), begin); diff --git a/src/main/java/dan200/computercraft/shared/util/ItemStorage.java b/src/main/java/dan200/computercraft/shared/util/ItemStorage.java index 01fd70887..eb6f790f0 100644 --- a/src/main/java/dan200/computercraft/shared/util/ItemStorage.java +++ b/src/main/java/dan200/computercraft/shared/util/ItemStorage.java @@ -35,6 +35,9 @@ static boolean areStackable(@Nonnull ItemStack a, @Nonnull ItemStack b) { int size(); + @Nonnull + ItemStack getStack(int slot); + @Nonnull ItemStack take(int slot, int limit, @Nonnull ItemStack filter, boolean simulate); @@ -57,6 +60,12 @@ public int size() { return this.inventory.size(); } + @Override + @Nonnull + public ItemStack getStack(int slot) { + return this.inventory.getStack(slot); + } + @Override @Nonnull public ItemStack take(int slot, int limit, @Nonnull ItemStack filter, boolean simulate) { @@ -203,6 +212,15 @@ public int size() { return this.size; } + @Override + @Nonnull + public ItemStack getStack(int slot) { + if (slot < this.start || slot >= this.start + this.size) { + return ItemStack.EMPTY; + } + return this.parent.getStack(slot - this.start ); + } + @Nonnull @Override public ItemStack take(int slot, int limit, @Nonnull ItemStack filter, boolean simulate) {