diff --git a/src/main/java/li/cil/oc2/api/bus/DeviceBus.java b/src/main/java/li/cil/oc2/api/bus/DeviceBus.java
index 68e3788f..f99da661 100644
--- a/src/main/java/li/cil/oc2/api/bus/DeviceBus.java
+++ b/src/main/java/li/cil/oc2/api/bus/DeviceBus.java
@@ -1,13 +1,13 @@
package li.cil.oc2.api.bus;
import li.cil.oc2.api.device.Device;
+import li.cil.oc2.api.device.IdentifiableDevice;
import java.util.Collection;
/**
* A device bus provides the interface by which {@link Device} can be made available
* to a {@link DeviceBusController}, which is usually used by VMs to access devices.
- *
*/
public interface DeviceBus {
/**
@@ -22,24 +22,24 @@ public interface DeviceBus {
*
* @param device the device to add to the bus.
*/
- void addDevice(Device device);
+ void addDevice(IdentifiableDevice device);
/**
* Removes a device from this device bus.
*
- * If the device has not been added with {@link #addDevice(Device)} before calling
+ * If the device has not been added with {@link #addDevice(IdentifiableDevice)} before calling
* this method, this method is a no-op.
*
* @param device the device to remove from the bus.
*/
- void removeDevice(Device device);
+ void removeDevice(IdentifiableDevice device);
/**
* The list of all devices currently registered with this device bus.
*
* @return the list of all devices that are currently on this bus.
*/
- Collection getDevices();
+ Collection getDevices();
/**
* Schedules a rescan of the device bus.
diff --git a/src/main/java/li/cil/oc2/api/bus/DeviceBusController.java b/src/main/java/li/cil/oc2/api/bus/DeviceBusController.java
index 247ade15..6714d377 100644
--- a/src/main/java/li/cil/oc2/api/bus/DeviceBusController.java
+++ b/src/main/java/li/cil/oc2/api/bus/DeviceBusController.java
@@ -1,6 +1,7 @@
package li.cil.oc2.api.bus;
import li.cil.oc2.api.device.Device;
+import li.cil.oc2.api.device.IdentifiableDevice;
import java.util.Collection;
@@ -11,7 +12,7 @@ import java.util.Collection;
*
* This interface is usually provided by VM containers and used to collect connected
* {@link Device}s by aggregating the devices that were added to the device bus elements
- * via {@link DeviceBusElement#addDevice(Device)}.
+ * via {@link DeviceBus#addDevice(IdentifiableDevice)}.
*
* The only way for {@link DeviceBusElement}s to be added to a bus is for a
* {@link DeviceBusController} to detect them during a scan.
@@ -54,5 +55,5 @@ public interface DeviceBusController {
*
* @return the list of all devices on the bus managed by this controller.
*/
- Collection getDevices();
+ Collection getDevices();
}
diff --git a/src/main/java/li/cil/oc2/api/bus/DeviceBusElement.java b/src/main/java/li/cil/oc2/api/bus/DeviceBusElement.java
index c496372e..d8d90668 100644
--- a/src/main/java/li/cil/oc2/api/bus/DeviceBusElement.java
+++ b/src/main/java/li/cil/oc2/api/bus/DeviceBusElement.java
@@ -1,6 +1,6 @@
package li.cil.oc2.api.bus;
-import li.cil.oc2.api.device.Device;
+import li.cil.oc2.api.device.IdentifiableDevice;
import javax.annotation.Nullable;
import java.util.Collection;
@@ -48,5 +48,5 @@ public interface DeviceBusElement extends DeviceBus {
*
* @return the devices that have been added to this element.
*/
- Collection getLocalDevices();
+ Collection getLocalDevices();
}
diff --git a/src/main/java/li/cil/oc2/api/device/Device.java b/src/main/java/li/cil/oc2/api/device/Device.java
index 1e3d4d30..3ffcf1bf 100644
--- a/src/main/java/li/cil/oc2/api/device/Device.java
+++ b/src/main/java/li/cil/oc2/api/device/Device.java
@@ -4,7 +4,6 @@ import li.cil.oc2.api.bus.DeviceBus;
import li.cil.oc2.api.device.object.ObjectDevice;
import java.util.List;
-import java.util.UUID;
/**
* Defines a device that may be added to a {@link DeviceBus}.
@@ -15,21 +14,12 @@ import java.util.UUID;
* @see ObjectDevice
*/
public interface Device {
- /**
- * An id unique to this device.
- *
- * This id must persist over save/load to prevent code in a running VM losing
- * track of the device.
- */
- UUID getUniqueId();
-
/**
* A list of device type names for this device.
*
* Devices may be identified by multiple type names. Although every atomic
* implementation will usually only have one, when compounding such modular
- * devices into a {@link CompoundDevice} all the underlying type names can
- * thus be retained.
+ * devices all the underlying type names can thus be retained.
*
* In a more general sense, these can be considered tags the device can be
* referenced by inside a VM.
diff --git a/src/main/java/li/cil/oc2/api/device/IdentifiableDevice.java b/src/main/java/li/cil/oc2/api/device/IdentifiableDevice.java
new file mode 100644
index 00000000..043911c4
--- /dev/null
+++ b/src/main/java/li/cil/oc2/api/device/IdentifiableDevice.java
@@ -0,0 +1,23 @@
+package li.cil.oc2.api.device;
+
+import java.util.UUID;
+
+/**
+ * Specialization of devices that allows referencing the device by a {@link UUID}.
+ *
+ * This type is required when adding devices to a {@link li.cil.oc2.api.bus.DeviceBus}
+ * or referencing devices on a bus. Some {@link li.cil.oc2.api.bus.DeviceBusElement}s
+ * may take care of wrapping connected devices automatically.
+ *
+ * Note that {@link li.cil.oc2.api.device.provider.DeviceProvider}s are not
+ * required to return identifiable devices.
+ */
+public interface IdentifiableDevice extends Device {
+ /**
+ * An id unique to this device.
+ *
+ * This id must persist over save/load to prevent code in a running VM losing
+ * track of the device.
+ */
+ UUID getUniqueId();
+}
diff --git a/src/main/java/li/cil/oc2/common/vm/DeviceBusControllerImpl.java b/src/main/java/li/cil/oc2/common/bus/DeviceBusControllerImpl.java
similarity index 96%
rename from src/main/java/li/cil/oc2/common/vm/DeviceBusControllerImpl.java
rename to src/main/java/li/cil/oc2/common/bus/DeviceBusControllerImpl.java
index 60c29504..f87ed478 100644
--- a/src/main/java/li/cil/oc2/common/vm/DeviceBusControllerImpl.java
+++ b/src/main/java/li/cil/oc2/common/bus/DeviceBusControllerImpl.java
@@ -1,4 +1,4 @@
-package li.cil.oc2.common.vm;
+package li.cil.oc2.common.bus;
import com.google.gson.*;
import li.cil.ceres.api.Serialized;
@@ -7,7 +7,8 @@ import li.cil.oc2.api.bus.DeviceBusElement;
import li.cil.oc2.api.device.Device;
import li.cil.oc2.api.device.DeviceMethod;
import li.cil.oc2.api.device.DeviceMethodParameter;
-import li.cil.oc2.common.util.TileEntities;
+import li.cil.oc2.api.device.IdentifiableDevice;
+import li.cil.oc2.common.util.TileEntityUtils;
import li.cil.sedna.api.device.Steppable;
import li.cil.sedna.api.device.serial.SerialDevice;
import net.minecraft.tileentity.TileEntity;
@@ -50,7 +51,7 @@ public class DeviceBusControllerImpl implements DeviceBusController, Steppable {
private static final String MESSAGE_TYPE_INVOKE_METHOD = "invoke";
private final Set elements = new HashSet<>();
- private final ConcurrentHashMap devices = new ConcurrentHashMap<>();
+ private final ConcurrentHashMap devices = new ConcurrentHashMap<>();
private final SerialDevice serialDevice;
private final Gson gson;
@@ -92,7 +93,7 @@ public class DeviceBusControllerImpl implements DeviceBusController, Steppable {
public void scanDevices() {
devices.clear();
for (final DeviceBusElement element : elements) {
- for (final Device device : element.getLocalDevices()) {
+ for (final IdentifiableDevice device : element.getLocalDevices()) {
final UUID uuid = device.getUniqueId();
devices.putIfAbsent(uuid, device);
}
@@ -100,7 +101,7 @@ public class DeviceBusControllerImpl implements DeviceBusController, Steppable {
}
@Override
- public Collection getDevices() {
+ public Collection getDevices() {
return devices.values();
}
@@ -148,7 +149,7 @@ public class DeviceBusControllerImpl implements DeviceBusController, Steppable {
continue;
}
- final Optional capability = TileEntities.getInterfaceForSide(tileEntity, DeviceBusElement.class, edge.face);
+ final Optional capability = TileEntityUtils.getInterfaceForSide(tileEntity, DeviceBusElement.class, edge.face);
if (capability.isPresent()) {
if (busPositions.add(edge.position) && busPositions.size() > MAX_BUS_ELEMENT_COUNT) {
elements.clear();
@@ -159,7 +160,7 @@ public class DeviceBusControllerImpl implements DeviceBusController, Steppable {
elements.add(element);
for (final Direction face : faces) {
- final Optional otherCapability = TileEntities.getInterfaceForSide(tileEntity, DeviceBusElement.class, face);
+ final Optional otherCapability = TileEntityUtils.getInterfaceForSide(tileEntity, DeviceBusElement.class, face);
otherCapability.ifPresent(otherElement -> {
final boolean isConnectedToIncomingEdge = otherElement == element;
if (!isConnectedToIncomingEdge) {
@@ -423,9 +424,9 @@ public class DeviceBusControllerImpl implements DeviceBusController, Steppable {
}
}
- private static final class DeviceSerializer implements JsonSerializer {
+ private static final class DeviceSerializer implements JsonSerializer {
@Override
- public JsonElement serialize(final Device src, final Type typeOfSrc, final JsonSerializationContext context) {
+ public JsonElement serialize(final IdentifiableDevice src, final Type typeOfSrc, final JsonSerializationContext context) {
if (src == null) {
return JsonNull.INSTANCE;
}
diff --git a/src/main/java/li/cil/oc2/common/vm/DeviceBusElementImpl.java b/src/main/java/li/cil/oc2/common/bus/DeviceBusElementImpl.java
similarity index 75%
rename from src/main/java/li/cil/oc2/common/vm/DeviceBusElementImpl.java
rename to src/main/java/li/cil/oc2/common/bus/DeviceBusElementImpl.java
index d2d305b4..2672553f 100644
--- a/src/main/java/li/cil/oc2/common/vm/DeviceBusElementImpl.java
+++ b/src/main/java/li/cil/oc2/common/bus/DeviceBusElementImpl.java
@@ -1,8 +1,8 @@
-package li.cil.oc2.common.vm;
+package li.cil.oc2.common.bus;
import li.cil.oc2.api.bus.DeviceBusController;
import li.cil.oc2.api.bus.DeviceBusElement;
-import li.cil.oc2.api.device.Device;
+import li.cil.oc2.api.device.IdentifiableDevice;
import javax.annotation.Nullable;
import java.util.ArrayList;
@@ -11,7 +11,7 @@ import java.util.List;
import java.util.Optional;
public class DeviceBusElementImpl implements DeviceBusElement {
- private final List devices = new ArrayList<>();
+ private final List devices = new ArrayList<>();
@Nullable private DeviceBusController controller;
@Override
@@ -24,12 +24,12 @@ public class DeviceBusElementImpl implements DeviceBusElement {
}
@Override
- public Collection getLocalDevices() {
+ public Collection getLocalDevices() {
return devices;
}
@Override
- public void addDevice(final Device device) {
+ public void addDevice(final IdentifiableDevice device) {
devices.add(device);
if (controller != null) {
controller.scanDevices();
@@ -37,7 +37,7 @@ public class DeviceBusElementImpl implements DeviceBusElement {
}
@Override
- public void removeDevice(final Device device) {
+ public void removeDevice(final IdentifiableDevice device) {
devices.remove(device);
if (controller != null) {
controller.scanDevices();
@@ -45,7 +45,7 @@ public class DeviceBusElementImpl implements DeviceBusElement {
}
@Override
- public Collection getDevices() {
+ public Collection getDevices() {
if (controller != null) {
return controller.getDevices();
} else {
diff --git a/src/main/java/li/cil/oc2/common/bus/package-info.java b/src/main/java/li/cil/oc2/common/bus/package-info.java
new file mode 100644
index 00000000..851d41ee
--- /dev/null
+++ b/src/main/java/li/cil/oc2/common/bus/package-info.java
@@ -0,0 +1,7 @@
+@ParametersAreNonnullByDefault
+@MethodsReturnNonnullByDefault
+package li.cil.oc2.common.bus;
+
+import mcp.MethodsReturnNonnullByDefault;
+
+import javax.annotation.ParametersAreNonnullByDefault;
\ No newline at end of file
diff --git a/src/main/java/li/cil/oc2/common/device/IdentifiableDeviceImpl.java b/src/main/java/li/cil/oc2/common/device/IdentifiableDeviceImpl.java
new file mode 100644
index 00000000..af0fb74b
--- /dev/null
+++ b/src/main/java/li/cil/oc2/common/device/IdentifiableDeviceImpl.java
@@ -0,0 +1,48 @@
+package li.cil.oc2.common.device;
+
+import li.cil.oc2.api.device.Device;
+import li.cil.oc2.api.device.DeviceMethod;
+import li.cil.oc2.api.device.IdentifiableDevice;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.UUID;
+
+public final class IdentifiableDeviceImpl implements IdentifiableDevice {
+ private final Device device;
+ private final UUID uuid;
+
+ public IdentifiableDeviceImpl(final Device device, final UUID uuid) {
+ this.device = device;
+ this.uuid = uuid;
+ }
+
+ @Override
+ public UUID getUniqueId() {
+ return uuid;
+ }
+
+ @Override
+ public List getTypeNames() {
+ return device.getTypeNames();
+ }
+
+ @Override
+ public List getMethods() {
+ return device.getMethods();
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ final IdentifiableDeviceImpl that = (IdentifiableDeviceImpl) o;
+ return uuid.equals(that.uuid) &&
+ device.equals(that.device);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(uuid, device);
+ }
+}
diff --git a/src/main/java/li/cil/oc2/common/device/package-info.java b/src/main/java/li/cil/oc2/common/device/package-info.java
new file mode 100644
index 00000000..4f55c409
--- /dev/null
+++ b/src/main/java/li/cil/oc2/common/device/package-info.java
@@ -0,0 +1,7 @@
+@ParametersAreNonnullByDefault
+@MethodsReturnNonnullByDefault
+package li.cil.oc2.common.device;
+
+import mcp.MethodsReturnNonnullByDefault;
+
+import javax.annotation.ParametersAreNonnullByDefault;
\ No newline at end of file
diff --git a/src/test/java/li/cil/oc2/bus/DeviceBusTests.java b/src/test/java/li/cil/oc2/bus/DeviceBusTests.java
index 674f1b01..e1644b03 100644
--- a/src/test/java/li/cil/oc2/bus/DeviceBusTests.java
+++ b/src/test/java/li/cil/oc2/bus/DeviceBusTests.java
@@ -1,9 +1,9 @@
package li.cil.oc2.bus;
import li.cil.oc2.api.bus.DeviceBusElement;
-import li.cil.oc2.api.device.Device;
+import li.cil.oc2.api.device.IdentifiableDevice;
+import li.cil.oc2.common.bus.DeviceBusControllerImpl;
import li.cil.oc2.common.capabilities.Capabilities;
-import li.cil.oc2.common.vm.DeviceBusControllerImpl;
import li.cil.sedna.api.device.serial.SerialDevice;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
@@ -62,7 +62,7 @@ public class DeviceBusTests {
final DeviceBusElement busElement = mock(DeviceBusElement.class);
when(tileEntity.getCapability(eq(busElementCapability), any())).thenReturn(LazyOptional.of(() -> busElement));
- final Device device = mock(Device.class);
+ final IdentifiableDevice device = mock(IdentifiableDevice.class);
when(busElement.getLocalDevices()).thenReturn(Collections.singletonList(device));
when(device.getUniqueId()).thenReturn(UUID.randomUUID());
diff --git a/src/test/java/li/cil/oc2/vm/ObjectDeviceProtocolTests.java b/src/test/java/li/cil/oc2/vm/ObjectDeviceProtocolTests.java
index 75df9146..9733574e 100644
--- a/src/test/java/li/cil/oc2/vm/ObjectDeviceProtocolTests.java
+++ b/src/test/java/li/cil/oc2/vm/ObjectDeviceProtocolTests.java
@@ -3,15 +3,15 @@ package li.cil.oc2.vm;
import com.google.gson.*;
import it.unimi.dsi.fastutil.bytes.ByteArrayFIFOQueue;
import li.cil.oc2.api.bus.DeviceBusElement;
-import li.cil.oc2.api.device.AbstractDevice;
-import li.cil.oc2.api.device.Device;
import li.cil.oc2.api.device.DeviceMethod;
+import li.cil.oc2.api.device.IdentifiableDevice;
import li.cil.oc2.api.device.object.Callback;
import li.cil.oc2.api.device.object.ObjectDevice;
import li.cil.oc2.api.device.object.Parameter;
+import li.cil.oc2.common.bus.DeviceBusControllerImpl;
+import li.cil.oc2.common.bus.DeviceBusElementImpl;
import li.cil.oc2.common.capabilities.Capabilities;
-import li.cil.oc2.common.vm.DeviceBusControllerImpl;
-import li.cil.oc2.common.vm.DeviceBusElementImpl;
+import li.cil.oc2.common.device.IdentifiableDeviceImpl;
import li.cil.sedna.api.device.serial.SerialDevice;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
@@ -28,6 +28,7 @@ import javax.annotation.Nullable;
import java.io.ByteArrayOutputStream;
import java.util.Collections;
import java.util.List;
+import java.util.UUID;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.mock;
@@ -117,14 +118,15 @@ public class ObjectDeviceProtocolTests {
public void annotatedObject() {
final SimpleObject object = new SimpleObject();
final ObjectDevice device = new ObjectDevice(object);
+ final IdentifiableDeviceImpl identifiableDevice = new IdentifiableDeviceImpl(device, UUID.randomUUID());
- busElement.addDevice(device);
+ busElement.addDevice(identifiableDevice);
controller.scan(world, CONTROLLER_POS);
- Assertions.assertEquals(42 + 23, invokeMethod(device, "add", 42, 23).getAsInt());
+ Assertions.assertEquals(42 + 23, invokeMethod(identifiableDevice, "add", 42, 23).getAsInt());
}
- private JsonElement invokeMethod(final Device device, final String name, final Object... parameters) {
+ private JsonElement invokeMethod(final IdentifiableDevice device, final String name, final Object... parameters) {
final JsonObject request = new JsonObject();
request.addProperty("type", "invoke");
final JsonObject methodInvocation = new JsonObject();
@@ -241,16 +243,28 @@ public class ObjectDeviceProtocolTests {
}
}
- private static final class TestDevice extends AbstractDevice {
+ private static final class TestDevice implements IdentifiableDevice {
+ private static final UUID UUID = java.util.UUID.randomUUID();
+
private final DeviceMethod method;
public TestDevice(final DeviceMethod method) {
this.method = method;
}
+ @Override
+ public List getTypeNames() {
+ return Collections.singletonList(getClass().getSimpleName());
+ }
+
@Override
public List getMethods() {
return Collections.singletonList(method);
}
+
+ @Override
+ public UUID getUniqueId() {
+ return UUID;
+ }
}
}