mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-01-07 07:50:27 +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
|
# Minecraft
|
||||||
# MC version is specified in gradle.properties, as we need that in settings.gradle.
|
# 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
|
# 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"
|
fabric-loader = "0.14.17"
|
||||||
forge = "45.0.42"
|
forge = "45.0.42"
|
||||||
forgeSpi = "6.0.0"
|
forgeSpi = "6.0.0"
|
||||||
|
@ -14,18 +14,15 @@ import dan200.computercraft.api.peripheral.IPeripheral;
|
|||||||
import dan200.computercraft.api.peripheral.PeripheralType;
|
import dan200.computercraft.api.peripheral.PeripheralType;
|
||||||
import dan200.computercraft.shared.peripheral.generic.SidedGenericPeripheral;
|
import dan200.computercraft.shared.peripheral.generic.SidedGenericPeripheral;
|
||||||
import dan200.computercraft.shared.platform.FabricContainerTransfer;
|
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.ItemStorage;
|
||||||
import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant;
|
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.fabricmc.fabric.api.transfer.v1.storage.base.SingleSlotStorage;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.level.Level;
|
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.BlockEntity;
|
||||||
import net.minecraft.world.level.block.entity.ChestBlockEntity;
|
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@ -50,15 +47,25 @@ public class InventoryMethods implements GenericPeripheral {
|
|||||||
return ComputerCraftAPI.MOD_ID + ":inventory";
|
return ComputerCraftAPI.MOD_ID + ":inventory";
|
||||||
}
|
}
|
||||||
|
|
||||||
@LuaFunction(mainThread = true)
|
/**
|
||||||
public static int size(InventoryStorage inventory) {
|
* Wrapper over a {@link SlottedStorage}.
|
||||||
return inventory.getSlots().size();
|
* <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)
|
@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<>();
|
Map<Integer, Map<String, ?>> result = new HashMap<>();
|
||||||
var slots = inventory.getSlots();
|
var slots = inventory.storage().getSlots();
|
||||||
var size = slots.size();
|
var size = slots.size();
|
||||||
for (var i = 0; i < size; i++) {
|
for (var i = 0; i < size; i++) {
|
||||||
var stack = toStack(slots.get(i));
|
var stack = toStack(slots.get(i));
|
||||||
@ -70,22 +77,22 @@ public class InventoryMethods implements GenericPeripheral {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@LuaFunction(mainThread = true)
|
@LuaFunction(mainThread = true)
|
||||||
public static Map<String, ?> getItemDetail(InventoryStorage inventory, int slot) throws LuaException {
|
public static Map<String, ?> getItemDetail(StorageWrapper inventory, int slot) throws LuaException {
|
||||||
assertBetween(slot, 1, inventory.getSlots().size(), "Slot out of range (%s)");
|
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);
|
return stack.isEmpty() ? null : VanillaDetailRegistries.ITEM_STACK.getDetails(stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
@LuaFunction(mainThread = true)
|
@LuaFunction(mainThread = true)
|
||||||
public static long getItemLimit(InventoryStorage inventory, int slot) throws LuaException {
|
public static long getItemLimit(StorageWrapper inventory, int slot) throws LuaException {
|
||||||
assertBetween(slot, 1, inventory.getSlots().size(), "Slot out of range (%s)");
|
assertBetween(slot, 1, inventory.storage().getSlotCount(), "Slot out of range (%s)");
|
||||||
return inventory.getSlot(slot - 1).getCapacity();
|
return inventory.storage().getSlot(slot - 1).getCapacity();
|
||||||
}
|
}
|
||||||
|
|
||||||
@LuaFunction(mainThread = true)
|
@LuaFunction(mainThread = true)
|
||||||
public static int pushItems(
|
public static int pushItems(
|
||||||
InventoryStorage from, IComputerAccess computer,
|
StorageWrapper from, IComputerAccess computer,
|
||||||
String toName, int fromSlot, Optional<Integer> limit, Optional<Integer> toSlot
|
String toName, int fromSlot, Optional<Integer> limit, Optional<Integer> toSlot
|
||||||
) throws LuaException {
|
) throws LuaException {
|
||||||
// Find location to transfer to
|
// Find location to transfer to
|
||||||
@ -95,65 +102,68 @@ public class InventoryMethods implements GenericPeripheral {
|
|||||||
var to = extractHandler(location);
|
var to = extractHandler(location);
|
||||||
if (to == null) throw new LuaException("Target '" + toName + "' is not an inventory");
|
if (to == null) throw new LuaException("Target '" + toName + "' is not an inventory");
|
||||||
|
|
||||||
|
var fromStorage = from.storage();
|
||||||
|
|
||||||
// Validate slots
|
// Validate slots
|
||||||
int actualLimit = limit.orElse(Integer.MAX_VALUE);
|
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 (toSlot.isPresent()) assertBetween(toSlot.get(), 1, to.getSlots().size(), "To slot out of range (%s)");
|
||||||
|
|
||||||
if (actualLimit <= 0) return 0;
|
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)
|
@LuaFunction(mainThread = true)
|
||||||
public static int pullItems(
|
public static int pullItems(
|
||||||
InventoryStorage to, IComputerAccess computer,
|
StorageWrapper to, IComputerAccess computer,
|
||||||
String fromName, int fromSlot, Optional<Integer> limit, Optional<Integer> toSlot
|
String fromName, int fromSlot, Optional<Integer> limit, Optional<Integer> toSlot
|
||||||
) throws LuaException {
|
) throws LuaException {
|
||||||
// Find location to transfer to
|
// Find location to transfer to
|
||||||
var location = computer.getAvailablePeripheral(fromName);
|
var location = computer.getAvailablePeripheral(fromName);
|
||||||
if (location == null) throw new LuaException("Source '" + fromName + "' does not exist");
|
if (location == null) throw new LuaException("Source '" + fromName + "' does not exist");
|
||||||
|
|
||||||
|
var toStorage = to.storage();
|
||||||
|
|
||||||
var from = extractHandler(location);
|
var from = extractHandler(location);
|
||||||
if (from == null) throw new LuaException("Source '" + fromName + "' is not an inventory");
|
if (from == null) throw new LuaException("Source '" + fromName + "' is not an inventory");
|
||||||
|
|
||||||
// Validate slots
|
// Validate slots
|
||||||
int actualLimit = limit.orElse(Integer.MAX_VALUE);
|
int actualLimit = limit.orElse(Integer.MAX_VALUE);
|
||||||
assertBetween(fromSlot, 1, from.getSlots().size(), "From slot out of range (%s)");
|
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;
|
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.
|
@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) {
|
private static @Nullable SlottedStorage<ItemVariant> extractContainerImpl(Level level, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, @Nullable Direction direction) {
|
||||||
// ItemStorage returns a CombinedStorage rather than an InventoryStorage for double chests.
|
var internal = ItemStorage.SIDED.find(level, pos, state, blockEntity, null);
|
||||||
if (blockEntity instanceof ChestBlockEntity && state.getBlock() instanceof ChestBlock chestBlock) {
|
if (internal instanceof SlottedStorage<ItemVariant> storage) return storage;
|
||||||
var inventory = ChestBlock.getContainer(chestBlock, state, level, pos, true);
|
|
||||||
return inventory == null ? null : InventoryStorage.of(inventory, null);
|
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);
|
return 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static InventoryStorage extractHandler(IPeripheral peripheral) {
|
private static SlottedStorage<ItemVariant> extractHandler(IPeripheral peripheral) {
|
||||||
var object = peripheral.getTarget();
|
var object = peripheral.getTarget();
|
||||||
var direction = peripheral instanceof SidedGenericPeripheral sided ? sided.direction() : null;
|
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) {
|
if (object instanceof BlockEntity blockEntity) {
|
||||||
var found = extractContainer(blockEntity.getLevel(), blockEntity.getBlockPos(), blockEntity.getBlockState(), blockEntity, direction);
|
if (blockEntity.isRemoved()) return null;
|
||||||
if (found instanceof InventoryStorage storage) return storage;
|
|
||||||
|
var found = extractContainerImpl(blockEntity.getLevel(), blockEntity.getBlockPos(), blockEntity.getBlockState(), blockEntity, direction);
|
||||||
|
if (found != null) return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
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.
|
* @param limit The max number to move. {@link Integer#MAX_VALUE} for no limit.
|
||||||
* @return The number of items moved.
|
* @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 fromWrapper = FabricContainerTransfer.of(from).singleSlot(fromSlot);
|
||||||
var toWrapper = FabricContainerTransfer.of(to);
|
var toWrapper = FabricContainerTransfer.of(to);
|
||||||
|
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
|
|
||||||
package dan200.computercraft.shared.platform;
|
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.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.Storage;
|
||||||
import net.fabricmc.fabric.api.transfer.v1.storage.StorageUtil;
|
import net.fabricmc.fabric.api.transfer.v1.storage.StorageUtil;
|
||||||
import net.fabricmc.fabric.api.transfer.v1.storage.StorageView;
|
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) {
|
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);
|
return new SlottedImpl(storage);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,9 +68,9 @@ public class FabricContainerTransfer implements ContainerTransfer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static class SlottedImpl extends FabricContainerTransfer implements ContainerTransfer.Slotted {
|
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);
|
super(storage);
|
||||||
this.storage = 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
|
@Override
|
||||||
public boolean supportsInsertion() {
|
public boolean supportsInsertion() {
|
||||||
for (var slot : storage.getSlots()) {
|
for (var slot : storage.getSlots()) {
|
||||||
|
@ -153,7 +153,6 @@ class FakeNetHandler extends ServerGamePacketListenerImpl {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void send(Packet<?> packet, @Nullable PacketSendListener packetSendListener) {
|
public void send(Packet<?> packet, @Nullable PacketSendListener packetSendListener) {
|
||||||
super.send(packet, packetSendListener);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -47,7 +47,7 @@
|
|||||||
],
|
],
|
||||||
"depends": {
|
"depends": {
|
||||||
"fabricloader": ">=0.14.17",
|
"fabricloader": ">=0.14.17",
|
||||||
"fabric-api": ">=0.75.3",
|
"fabric-api": ">=0.78.0",
|
||||||
"minecraft": ">=1.19.4 <1.20"
|
"minecraft": ">=1.19.4 <1.20"
|
||||||
},
|
},
|
||||||
"accessWidener": "computercraft.accesswidener"
|
"accessWidener": "computercraft.accesswidener"
|
||||||
|
Loading…
Reference in New Issue
Block a user