From 5d7cbc8c64ea8f882d6ccb2688a2418a4e77d90e Mon Sep 17 00:00:00 2001 From: Jonathan Coates Date: Sun, 16 Apr 2023 09:16:39 +0100 Subject: [PATCH] Use Fabric's new SlottedStorage for inventory methods This is a little more general than InventoryStorage and means we can get rid of our nasty double chest hack. The generic peripheral system doesn't currently support generics (hah), and so we need to use a wrapper class for now. --- gradle/libs.versions.toml | 2 +- .../generic/methods/InventoryMethods.java | 92 ++++++++++--------- .../platform/FabricContainerTransfer.java | 12 +-- .../shared/platform/FakeNetHandler.java | 1 - .../fabric/src/main/resources/fabric.mod.json | 2 +- 5 files changed, 59 insertions(+), 50 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ca2805f25..9e8596c70 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ # Minecraft # MC version is specified in gradle.properties, as we need that in settings.gradle. # Remember to update corresponding versions in fabric.mod.json/mods.toml -fabric-api = "0.75.3+1.19.4" +fabric-api = "0.78.0+1.19.4" fabric-loader = "0.14.17" forge = "45.0.42" forgeSpi = "6.0.0" diff --git a/projects/fabric/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/InventoryMethods.java b/projects/fabric/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/InventoryMethods.java index 45012e403..fa15b1dd9 100644 --- a/projects/fabric/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/InventoryMethods.java +++ b/projects/fabric/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/InventoryMethods.java @@ -14,18 +14,15 @@ import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.peripheral.PeripheralType; import dan200.computercraft.shared.peripheral.generic.SidedGenericPeripheral; import dan200.computercraft.shared.platform.FabricContainerTransfer; -import net.fabricmc.fabric.api.transfer.v1.item.InventoryStorage; import net.fabricmc.fabric.api.transfer.v1.item.ItemStorage; import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant; -import net.fabricmc.fabric.api.transfer.v1.storage.Storage; +import net.fabricmc.fabric.api.transfer.v1.storage.SlottedStorage; import net.fabricmc.fabric.api.transfer.v1.storage.base.SingleSlotStorage; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.ChestBlock; import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.ChestBlockEntity; import net.minecraft.world.level.block.state.BlockState; import javax.annotation.Nullable; @@ -50,15 +47,25 @@ public class InventoryMethods implements GenericPeripheral { return ComputerCraftAPI.MOD_ID + ":inventory"; } - @LuaFunction(mainThread = true) - public static int size(InventoryStorage inventory) { - return inventory.getSlots().size(); + /** + * Wrapper over a {@link SlottedStorage}. + *

+ * The generic peripheral system doesn't (currently) support generics, and so we need put the inventory in a box. + * + * @param storage The underlying storage + */ + public record StorageWrapper(SlottedStorage storage) { } @LuaFunction(mainThread = true) - public static Map> list(InventoryStorage inventory) { + public static int size(StorageWrapper inventory) { + return inventory.storage().getSlots().size(); + } + + @LuaFunction(mainThread = true) + public static Map> list(StorageWrapper inventory) { Map> result = new HashMap<>(); - var slots = inventory.getSlots(); + var slots = inventory.storage().getSlots(); var size = slots.size(); for (var i = 0; i < size; i++) { var stack = toStack(slots.get(i)); @@ -70,22 +77,22 @@ public class InventoryMethods implements GenericPeripheral { @Nullable @LuaFunction(mainThread = true) - public static Map getItemDetail(InventoryStorage inventory, int slot) throws LuaException { - assertBetween(slot, 1, inventory.getSlots().size(), "Slot out of range (%s)"); + public static Map getItemDetail(StorageWrapper inventory, int slot) throws LuaException { + assertBetween(slot, 1, inventory.storage().getSlotCount(), "Slot out of range (%s)"); - var stack = toStack(inventory.getSlot(slot - 1)); + var stack = toStack(inventory.storage().getSlot(slot - 1)); return stack.isEmpty() ? null : VanillaDetailRegistries.ITEM_STACK.getDetails(stack); } @LuaFunction(mainThread = true) - public static long getItemLimit(InventoryStorage inventory, int slot) throws LuaException { - assertBetween(slot, 1, inventory.getSlots().size(), "Slot out of range (%s)"); - return inventory.getSlot(slot - 1).getCapacity(); + public static long getItemLimit(StorageWrapper inventory, int slot) throws LuaException { + assertBetween(slot, 1, inventory.storage().getSlotCount(), "Slot out of range (%s)"); + return inventory.storage().getSlot(slot - 1).getCapacity(); } @LuaFunction(mainThread = true) public static int pushItems( - InventoryStorage from, IComputerAccess computer, + StorageWrapper from, IComputerAccess computer, String toName, int fromSlot, Optional limit, Optional toSlot ) throws LuaException { // Find location to transfer to @@ -95,65 +102,68 @@ public class InventoryMethods implements GenericPeripheral { var to = extractHandler(location); if (to == null) throw new LuaException("Target '" + toName + "' is not an inventory"); + var fromStorage = from.storage(); + // Validate slots int actualLimit = limit.orElse(Integer.MAX_VALUE); - assertBetween(fromSlot, 1, from.getSlots().size(), "From slot out of range (%s)"); + assertBetween(fromSlot, 1, fromStorage.getSlotCount(), "From slot out of range (%s)"); if (toSlot.isPresent()) assertBetween(toSlot.get(), 1, to.getSlots().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, to, toSlot.orElse(0) - 1, actualLimit); } @LuaFunction(mainThread = true) public static int pullItems( - InventoryStorage to, IComputerAccess computer, + StorageWrapper to, IComputerAccess computer, String fromName, int fromSlot, Optional limit, Optional toSlot ) throws LuaException { // Find location to transfer to var location = computer.getAvailablePeripheral(fromName); if (location == null) throw new LuaException("Source '" + fromName + "' does not exist"); + var toStorage = to.storage(); + var from = extractHandler(location); if (from == null) throw new LuaException("Source '" + fromName + "' is not an inventory"); // Validate slots int actualLimit = limit.orElse(Integer.MAX_VALUE); assertBetween(fromSlot, 1, from.getSlots().size(), "From slot out of range (%s)"); - if (toSlot.isPresent()) assertBetween(toSlot.get(), 1, to.getSlots().size(), "To slot out of range (%s)"); + if (toSlot.isPresent()) assertBetween(toSlot.get(), 1, toStorage.getSlotCount(), "To slot out of range (%s)"); if (actualLimit <= 0) return 0; - return moveItem(from, fromSlot - 1, to, toSlot.orElse(0) - 1, actualLimit); + return moveItem(from, fromSlot - 1, toStorage, toSlot.orElse(0) - 1, actualLimit); + } + + public static @Nullable StorageWrapper extractContainer(Level level, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, @Nullable Direction direction) { + var storage = extractContainerImpl(level, pos, state, blockEntity, direction); + return storage == null ? null : new StorageWrapper(storage); } @SuppressWarnings("NullAway") // FIXME: Doesn't cope with @Nullable type parameter. - public static @Nullable Storage extractContainer(Level level, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, @Nullable Direction direction) { - // ItemStorage returns a CombinedStorage rather than an InventoryStorage for double chests. - if (blockEntity instanceof ChestBlockEntity && state.getBlock() instanceof ChestBlock chestBlock) { - var inventory = ChestBlock.getContainer(chestBlock, state, level, pos, true); - return inventory == null ? null : InventoryStorage.of(inventory, null); + private static @Nullable SlottedStorage extractContainerImpl(Level level, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, @Nullable Direction direction) { + var internal = ItemStorage.SIDED.find(level, pos, state, blockEntity, null); + if (internal instanceof SlottedStorage storage) return storage; + + if (direction != null) { + var external = ItemStorage.SIDED.find(level, pos, state, blockEntity, direction); + if (external instanceof SlottedStorage storage) return storage; } - var internal = ItemStorage.SIDED.find(level, pos, state, blockEntity, null); - if (internal instanceof InventoryStorage || direction == null) return internal; - - var external = ItemStorage.SIDED.find(level, pos, state, blockEntity, direction); - if (external instanceof InventoryStorage) return external; - - return internal != null ? internal : external; + return null; } @Nullable - private static InventoryStorage extractHandler(IPeripheral peripheral) { + private static SlottedStorage extractHandler(IPeripheral peripheral) { var object = peripheral.getTarget(); var direction = peripheral instanceof SidedGenericPeripheral sided ? sided.direction() : null; - if (object instanceof BlockEntity blockEntity && blockEntity.isRemoved()) return null; - - if (object instanceof InventoryStorage storage) return storage; - if (object instanceof BlockEntity blockEntity) { - var found = extractContainer(blockEntity.getLevel(), blockEntity.getBlockPos(), blockEntity.getBlockState(), blockEntity, direction); - if (found instanceof InventoryStorage storage) return storage; + if (blockEntity.isRemoved()) return null; + + var found = extractContainerImpl(blockEntity.getLevel(), blockEntity.getBlockPos(), blockEntity.getBlockState(), blockEntity, direction); + if (found != null) return found; } return null; @@ -169,7 +179,7 @@ public class InventoryMethods implements GenericPeripheral { * @param limit The max number to move. {@link Integer#MAX_VALUE} for no limit. * @return The number of items moved. */ - private static int moveItem(InventoryStorage from, int fromSlot, InventoryStorage to, int toSlot, final int limit) { + private static int moveItem(SlottedStorage from, int fromSlot, SlottedStorage to, int toSlot, final int limit) { var fromWrapper = FabricContainerTransfer.of(from).singleSlot(fromSlot); var toWrapper = FabricContainerTransfer.of(to); diff --git a/projects/fabric/src/main/java/dan200/computercraft/shared/platform/FabricContainerTransfer.java b/projects/fabric/src/main/java/dan200/computercraft/shared/platform/FabricContainerTransfer.java index 5036fffc7..589fe2235 100644 --- a/projects/fabric/src/main/java/dan200/computercraft/shared/platform/FabricContainerTransfer.java +++ b/projects/fabric/src/main/java/dan200/computercraft/shared/platform/FabricContainerTransfer.java @@ -4,8 +4,8 @@ package dan200.computercraft.shared.platform; -import net.fabricmc.fabric.api.transfer.v1.item.InventoryStorage; import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant; +import net.fabricmc.fabric.api.transfer.v1.storage.SlottedStorage; import net.fabricmc.fabric.api.transfer.v1.storage.Storage; import net.fabricmc.fabric.api.transfer.v1.storage.StorageUtil; import net.fabricmc.fabric.api.transfer.v1.storage.StorageView; @@ -25,10 +25,10 @@ public class FabricContainerTransfer implements ContainerTransfer { } public static ContainerTransfer of(Storage storage) { - return storage instanceof InventoryStorage inv ? new SlottedImpl(inv) : new FabricContainerTransfer(storage); + return storage instanceof SlottedStorage inv ? new SlottedImpl(inv) : new FabricContainerTransfer(storage); } - public static ContainerTransfer.Slotted of(InventoryStorage storage) { + public static ContainerTransfer.Slotted of(SlottedStorage storage) { return new SlottedImpl(storage); } @@ -68,9 +68,9 @@ public class FabricContainerTransfer implements ContainerTransfer { } private static class SlottedImpl extends FabricContainerTransfer implements ContainerTransfer.Slotted { - private final InventoryStorage storage; + private final SlottedStorage storage; - SlottedImpl(InventoryStorage storage) { + SlottedImpl(SlottedStorage storage) { super(storage); this.storage = storage; } @@ -86,7 +86,7 @@ public class FabricContainerTransfer implements ContainerTransfer { } } - private record OffsetStorage(InventoryStorage storage, int offset) implements Storage { + private record OffsetStorage(SlottedStorage storage, int offset) implements Storage { @Override public boolean supportsInsertion() { for (var slot : storage.getSlots()) { diff --git a/projects/fabric/src/main/java/dan200/computercraft/shared/platform/FakeNetHandler.java b/projects/fabric/src/main/java/dan200/computercraft/shared/platform/FakeNetHandler.java index 633826e3c..ddbe5f737 100644 --- a/projects/fabric/src/main/java/dan200/computercraft/shared/platform/FakeNetHandler.java +++ b/projects/fabric/src/main/java/dan200/computercraft/shared/platform/FakeNetHandler.java @@ -153,7 +153,6 @@ class FakeNetHandler extends ServerGamePacketListenerImpl { @Override public void send(Packet packet, @Nullable PacketSendListener packetSendListener) { - super.send(packet, packetSendListener); } @Override diff --git a/projects/fabric/src/main/resources/fabric.mod.json b/projects/fabric/src/main/resources/fabric.mod.json index bb09ea85f..0e638d0c4 100644 --- a/projects/fabric/src/main/resources/fabric.mod.json +++ b/projects/fabric/src/main/resources/fabric.mod.json @@ -47,7 +47,7 @@ ], "depends": { "fabricloader": ">=0.14.17", - "fabric-api": ">=0.75.3", + "fabric-api": ">=0.78.0", "minecraft": ">=1.19.4 <1.20" }, "accessWidener": "computercraft.accesswidener"