diff --git a/src/main/java/li/cil/oc2/api/bus/device/provider/DeviceProvider.java b/src/main/java/li/cil/oc2/api/bus/device/provider/DeviceProvider.java
index 17ec1c37..cc834535 100644
--- a/src/main/java/li/cil/oc2/api/bus/device/provider/DeviceProvider.java
+++ b/src/main/java/li/cil/oc2/api/bus/device/provider/DeviceProvider.java
@@ -9,11 +9,6 @@ import net.minecraftforge.common.util.LazyOptional;
* Allows querying for devices given some context.
*
* See the specializations of {@link DeviceQuery} for possible queries.
- *
- * Returning a devices does not transfer ownership of the device in terms
- * of responsibility for persistence. Callers of this method will not attempt
- * to persist objects returned by this method. It is the responsibility of the provider
- * to ensure persistence where required.
*
* - Implementations may handle multiple query types and return various device
* types depending on the query.
diff --git a/src/main/java/li/cil/oc2/api/bus/device/provider/ItemDeviceQuery.java b/src/main/java/li/cil/oc2/api/bus/device/provider/ItemDeviceQuery.java
new file mode 100644
index 00000000..1611cffb
--- /dev/null
+++ b/src/main/java/li/cil/oc2/api/bus/device/provider/ItemDeviceQuery.java
@@ -0,0 +1,4 @@
+package li.cil.oc2.api.bus.device.provider;
+
+public interface ItemDeviceQuery extends DeviceQuery {
+}
diff --git a/src/main/java/li/cil/oc2/common/block/entity/ComputerTileEntity.java b/src/main/java/li/cil/oc2/common/block/entity/ComputerTileEntity.java
index a4dbc371..d59f27d9 100644
--- a/src/main/java/li/cil/oc2/common/block/entity/ComputerTileEntity.java
+++ b/src/main/java/li/cil/oc2/common/block/entity/ComputerTileEntity.java
@@ -10,6 +10,7 @@ import li.cil.oc2.common.block.ComputerBlock;
import li.cil.oc2.common.bus.AbstractDeviceBusController;
import li.cil.oc2.common.bus.TileEntityDeviceBusElement;
import li.cil.oc2.common.capabilities.Capabilities;
+import li.cil.oc2.common.container.DeviceItemStackHandler;
import li.cil.oc2.common.network.Network;
import li.cil.oc2.common.network.message.ComputerBusStateMessage;
import li.cil.oc2.common.network.message.ComputerRunStateMessage;
@@ -42,7 +43,6 @@ import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
-import net.minecraftforge.items.ItemStackHandler;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.NotNull;
@@ -51,8 +51,7 @@ import javax.annotation.Nullable;
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.nio.ByteBuffer;
-import java.util.Set;
-import java.util.UUID;
+import java.util.*;
import static java.util.Objects.requireNonNull;
@@ -69,6 +68,7 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic
private static final String VFS_NBT_TAG_NAME = "vfs";
private static final String RUNNER_NBT_TAG_NAME = "runner";
private static final String RUN_STATE_NBT_TAG_NAME = "runState";
+ private static final String ITEMS_NBT_TAG_NAME = "items";
private static final int DEVICE_LOAD_RETRY_INTERVAL = 10 * 20; // In ticks.
@@ -100,7 +100,7 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic
private PhysicalMemory ram;
private UUID ramBlobHandle;
- private final ItemStackHandler itemHandler = new ItemStackHandler();
+ private final DeviceItemStackHandler itemHandler = new DeviceItemStackHandler(4);
///////////////////////////////////////////////////////////////////
@@ -287,6 +287,8 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic
NBTUtils.putEnum(compound, RUN_STATE_NBT_TAG_NAME, runState);
}
+ compound.put(ITEMS_NBT_TAG_NAME, itemHandler.serializeNBT());
+
final ListNBT devicesNbt = new ListNBT();
writeDevices(devicesNbt);
compound.put(DEVICES_NBT_TAG_NAME, devicesNbt);
@@ -331,7 +333,9 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic
}
}
- // TODO Read item NBTs, generate item based devices.
+ if (compound.contains(ITEMS_NBT_TAG_NAME, NBTTagIds.TAG_COMPOUND)) {
+ itemHandler.deserializeNBT(compound.getCompound(ITEMS_NBT_TAG_NAME));
+ }
if (compound.contains(DEVICES_NBT_TAG_NAME, NBTTagIds.TAG_LIST)) {
readDevices(compound.getList(DEVICES_NBT_TAG_NAME, NBTTagIds.TAG_COMPOUND));
@@ -509,6 +513,15 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic
super(ComputerTileEntity.this);
}
+ @Override
+ public Optional>> getNeighbors() {
+ return super.getNeighbors().map(neighbors -> {
+ final ArrayList> list = new ArrayList<>(neighbors);
+ list.add(LazyOptional.of(itemHandler::getBusElement));
+ return list;
+ });
+ }
+
@Override
protected boolean canConnectToSide(final Direction direction) {
return getBlockState().get(ComputerBlock.HORIZONTAL_FACING) != direction;
diff --git a/src/main/java/li/cil/oc2/common/bus/ItemHandlerDeviceBusElement.java b/src/main/java/li/cil/oc2/common/bus/ItemHandlerDeviceBusElement.java
new file mode 100644
index 00000000..6005f2b7
--- /dev/null
+++ b/src/main/java/li/cil/oc2/common/bus/ItemHandlerDeviceBusElement.java
@@ -0,0 +1,33 @@
+package li.cil.oc2.common.bus;
+
+import li.cil.oc2.api.bus.device.Device;
+import li.cil.oc2.common.bus.device.provider.Providers;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.common.util.LazyOptional;
+import net.minecraftforge.items.ItemStackHandler;
+
+import java.util.HashSet;
+
+public class ItemHandlerDeviceBusElement extends AbstractGroupingDeviceBusElement {
+ private final ItemStackHandler handler;
+
+ ///////////////////////////////////////////////////////////////////
+
+ public ItemHandlerDeviceBusElement(final ItemStackHandler handler) {
+ super(handler.getSlots());
+ this.handler = handler;
+ }
+
+ public void handleSlotChanged(final int slot) {
+ final HashSet newDevices = new HashSet<>();
+ final ItemStack stack = handler.getStackInSlot(slot);
+ if (!stack.isEmpty()) {
+ for (final LazyOptional device : Providers.getDevices(stack)) {
+ device.ifPresent(newDevices::add);
+ device.addListener(unused -> handleSlotChanged(slot));
+ }
+ }
+
+ setDevicesForGroup(slot, newDevices);
+ }
+}
diff --git a/src/main/java/li/cil/oc2/common/bus/device/provider/Providers.java b/src/main/java/li/cil/oc2/common/bus/device/provider/Providers.java
index ef043cda..2954702f 100644
--- a/src/main/java/li/cil/oc2/common/bus/device/provider/Providers.java
+++ b/src/main/java/li/cil/oc2/common/bus/device/provider/Providers.java
@@ -4,8 +4,10 @@ import li.cil.oc2.api.bus.device.Device;
import li.cil.oc2.api.bus.device.provider.BlockDeviceQuery;
import li.cil.oc2.api.bus.device.provider.DeviceProvider;
import li.cil.oc2.api.bus.device.provider.DeviceQuery;
+import li.cil.oc2.api.bus.device.provider.ItemDeviceQuery;
import li.cil.oc2.common.bus.device.provider.util.BlockDeviceProvider;
import li.cil.oc2.common.bus.device.provider.util.TileEntityDeviceProvider;
+import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
@@ -48,6 +50,10 @@ public final class Providers {
return getDevices(new BlockQuery(world, pos, side));
}
+ public static List> getDevices(final ItemStack stack) {
+ return getDevices(new ItemQuery(stack));
+ }
+
public static List> getDevices(final DeviceQuery query) {
final ArrayList> devices = new ArrayList<>();
for (final DeviceProvider provider : DEVICE_PROVIDERS) {
@@ -88,4 +94,12 @@ public final class Providers {
return side;
}
}
+
+ private static final class ItemQuery implements ItemDeviceQuery {
+ private final ItemStack stack;
+
+ public ItemQuery(final ItemStack stack) {
+ this.stack = stack;
+ }
+ }
}
diff --git a/src/main/java/li/cil/oc2/common/container/DeviceItemStackHandler.java b/src/main/java/li/cil/oc2/common/container/DeviceItemStackHandler.java
index f4b7dbc0..4b46b39b 100644
--- a/src/main/java/li/cil/oc2/common/container/DeviceItemStackHandler.java
+++ b/src/main/java/li/cil/oc2/common/container/DeviceItemStackHandler.java
@@ -1,21 +1,22 @@
package li.cil.oc2.common.container;
-import li.cil.oc2.api.bus.Device;
-import li.cil.oc2.common.bus.device.provider.Providers;
+import li.cil.oc2.api.bus.DeviceBusElement;
+import li.cil.oc2.common.bus.ItemHandlerDeviceBusElement;
+import li.cil.oc2.common.util.NBTTagIds;
import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.NonNullList;
-import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.ItemStackHandler;
import org.jetbrains.annotations.NotNull;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.UUID;
-
public class DeviceItemStackHandler extends ItemStackHandler {
- private final HashSet devices = new HashSet<>();
- private final UUID[] deviceIds;
+ private static final String BUS_ELEMENT_NBT_TAG_NAME = "busElement";
+
+ ///////////////////////////////////////////////////////////////////
+
+ private final ItemHandlerDeviceBusElement busElement;
+
+ ///////////////////////////////////////////////////////////////////
public DeviceItemStackHandler(final int size) {
this(NonNullList.withSize(size, ItemStack.EMPTY));
@@ -23,9 +24,26 @@ public class DeviceItemStackHandler extends ItemStackHandler {
public DeviceItemStackHandler(final NonNullList stacks) {
super(stacks);
- deviceIds = new UUID[stacks.size()];
- for (int i = 0; i < deviceIds.length; i++) {
- deviceIds[i] = UUID.randomUUID();
+ this.busElement = new ItemHandlerDeviceBusElement(this);
+ }
+
+ public DeviceBusElement getBusElement() {
+ return busElement;
+ }
+
+ @Override
+ public CompoundNBT serializeNBT() {
+ final CompoundNBT nbt = super.serializeNBT();
+ nbt.put(BUS_ELEMENT_NBT_TAG_NAME, busElement.serializeNBT());
+ return nbt;
+ }
+
+ @Override
+ public void deserializeNBT(final CompoundNBT nbt) {
+ super.deserializeNBT(nbt);
+ busElement.deserializeNBT(nbt.getList(BUS_ELEMENT_NBT_TAG_NAME, NBTTagIds.TAG_COMPOUND));
+ for (int i = 0; i < getSlots(); i++) {
+ busElement.handleSlotChanged(i);
}
}
@@ -39,26 +57,11 @@ public class DeviceItemStackHandler extends ItemStackHandler {
return 1;
}
+ ///////////////////////////////////////////////////////////////////
+
@Override
- protected void onLoad() {
- super.onLoad();
-
- final HashSet newDevices = new HashSet<>();
- for (int i = 0; i < getSlots(); i++) {
- final ItemStack stack = getStackInSlot(i);
- if (stack.isEmpty()) {
- continue;
- }
-
-// final List> devices = Providers.getDevices(stack);
- }
- }
-
- protected void onDevicesAdded(final Set devices) {
-
- }
-
- protected void onDevicesRemoved(final Set devices) {
-
+ protected void onContentsChanged(final int slot) {
+ super.onContentsChanged(slot);
+ busElement.handleSlotChanged(slot);
}
}