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"