mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2024-12-14 12:10:30 +00:00
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.
This commit is contained in:
parent
e8fd460935
commit
5d7cbc8c64
@ -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"
|
||||
|
@ -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}.
|
||||
* <p>
|
||||
* 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<ItemVariant> storage) {
|
||||
}
|
||||
|
||||
@LuaFunction(mainThread = true)
|
||||
public static Map<Integer, Map<String, ?>> list(InventoryStorage inventory) {
|
||||
public static int size(StorageWrapper inventory) {
|
||||
return inventory.storage().getSlots().size();
|
||||
}
|
||||
|
||||
@LuaFunction(mainThread = true)
|
||||
public static Map<Integer, Map<String, ?>> list(StorageWrapper inventory) {
|
||||
Map<Integer, Map<String, ?>> 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<String, ?> getItemDetail(InventoryStorage inventory, int slot) throws LuaException {
|
||||
assertBetween(slot, 1, inventory.getSlots().size(), "Slot out of range (%s)");
|
||||
public static Map<String, ?> 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<Integer> limit, Optional<Integer> 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<Integer> limit, Optional<Integer> 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<ItemVariant> 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<ItemVariant> 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<ItemVariant> storage) return storage;
|
||||
|
||||
if (direction != null) {
|
||||
var external = ItemStorage.SIDED.find(level, pos, state, blockEntity, direction);
|
||||
if (external instanceof SlottedStorage<ItemVariant> 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<ItemVariant> 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<ItemVariant> from, int fromSlot, SlottedStorage<ItemVariant> to, int toSlot, final int limit) {
|
||||
var fromWrapper = FabricContainerTransfer.of(from).singleSlot(fromSlot);
|
||||
var toWrapper = FabricContainerTransfer.of(to);
|
||||
|
||||
|
@ -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<ItemVariant> storage) {
|
||||
return storage instanceof InventoryStorage inv ? new SlottedImpl(inv) : new FabricContainerTransfer(storage);
|
||||
return storage instanceof SlottedStorage<ItemVariant> inv ? new SlottedImpl(inv) : new FabricContainerTransfer(storage);
|
||||
}
|
||||
|
||||
public static ContainerTransfer.Slotted of(InventoryStorage storage) {
|
||||
public static ContainerTransfer.Slotted of(SlottedStorage<ItemVariant> 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<ItemVariant> storage;
|
||||
|
||||
SlottedImpl(InventoryStorage storage) {
|
||||
SlottedImpl(SlottedStorage<ItemVariant> storage) {
|
||||
super(storage);
|
||||
this.storage = storage;
|
||||
}
|
||||
@ -86,7 +86,7 @@ public class FabricContainerTransfer implements ContainerTransfer {
|
||||
}
|
||||
}
|
||||
|
||||
private record OffsetStorage(InventoryStorage storage, int offset) implements Storage<ItemVariant> {
|
||||
private record OffsetStorage(SlottedStorage<ItemVariant> storage, int offset) implements Storage<ItemVariant> {
|
||||
@Override
|
||||
public boolean supportsInsertion() {
|
||||
for (var slot : storage.getSlots()) {
|
||||
|
@ -153,7 +153,6 @@ class FakeNetHandler extends ServerGamePacketListenerImpl {
|
||||
|
||||
@Override
|
||||
public void send(Packet<?> packet, @Nullable PacketSendListener packetSendListener) {
|
||||
super.send(packet, packetSendListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user