Split out identifier for devices into separate sub-interface.
It's only needed at bus level so we can wrap at that point.
This commit is contained in:
@@ -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.
|
||||
* <p>
|
||||
*/
|
||||
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.
|
||||
* <p>
|
||||
* 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<Device> getDevices();
|
||||
Collection<IdentifiableDevice> getDevices();
|
||||
|
||||
/**
|
||||
* Schedules a rescan of the device bus.
|
||||
|
||||
@@ -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;
|
||||
* <p>
|
||||
* 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)}.
|
||||
* <p>
|
||||
* 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<Device> getDevices();
|
||||
Collection<IdentifiableDevice> getDevices();
|
||||
}
|
||||
|
||||
@@ -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<Device> getLocalDevices();
|
||||
Collection<IdentifiableDevice> getLocalDevices();
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* In a more general sense, these can be considered tags the device can be
|
||||
* referenced by inside a VM.
|
||||
|
||||
23
src/main/java/li/cil/oc2/api/device/IdentifiableDevice.java
Normal file
23
src/main/java/li/cil/oc2/api/device/IdentifiableDevice.java
Normal file
@@ -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}.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* Note that {@link li.cil.oc2.api.device.provider.DeviceProvider}s are <em>not</em>
|
||||
* required to return identifiable devices.
|
||||
*/
|
||||
public interface IdentifiableDevice extends Device {
|
||||
/**
|
||||
* An id unique to this device.
|
||||
* <p>
|
||||
* This id must persist over save/load to prevent code in a running VM losing
|
||||
* track of the device.
|
||||
*/
|
||||
UUID getUniqueId();
|
||||
}
|
||||
@@ -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<DeviceBusElement> elements = new HashSet<>();
|
||||
private final ConcurrentHashMap<UUID, Device> devices = new ConcurrentHashMap<>();
|
||||
private final ConcurrentHashMap<UUID, IdentifiableDevice> 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<Device> getDevices() {
|
||||
public Collection<IdentifiableDevice> getDevices() {
|
||||
return devices.values();
|
||||
}
|
||||
|
||||
@@ -148,7 +149,7 @@ public class DeviceBusControllerImpl implements DeviceBusController, Steppable {
|
||||
continue;
|
||||
}
|
||||
|
||||
final Optional<DeviceBusElement> capability = TileEntities.getInterfaceForSide(tileEntity, DeviceBusElement.class, edge.face);
|
||||
final Optional<DeviceBusElement> 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<DeviceBusElement> otherCapability = TileEntities.getInterfaceForSide(tileEntity, DeviceBusElement.class, face);
|
||||
final Optional<DeviceBusElement> 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<Device> {
|
||||
private static final class DeviceSerializer implements JsonSerializer<IdentifiableDevice> {
|
||||
@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;
|
||||
}
|
||||
@@ -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<Device> devices = new ArrayList<>();
|
||||
private final List<IdentifiableDevice> devices = new ArrayList<>();
|
||||
@Nullable private DeviceBusController controller;
|
||||
|
||||
@Override
|
||||
@@ -24,12 +24,12 @@ public class DeviceBusElementImpl implements DeviceBusElement {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Device> getLocalDevices() {
|
||||
public Collection<IdentifiableDevice> 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<Device> getDevices() {
|
||||
public Collection<IdentifiableDevice> getDevices() {
|
||||
if (controller != null) {
|
||||
return controller.getDevices();
|
||||
} else {
|
||||
7
src/main/java/li/cil/oc2/common/bus/package-info.java
Normal file
7
src/main/java/li/cil/oc2/common/bus/package-info.java
Normal file
@@ -0,0 +1,7 @@
|
||||
@ParametersAreNonnullByDefault
|
||||
@MethodsReturnNonnullByDefault
|
||||
package li.cil.oc2.common.bus;
|
||||
|
||||
import mcp.MethodsReturnNonnullByDefault;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
@@ -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<String> getTypeNames() {
|
||||
return device.getTypeNames();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DeviceMethod> 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);
|
||||
}
|
||||
}
|
||||
7
src/main/java/li/cil/oc2/common/device/package-info.java
Normal file
7
src/main/java/li/cil/oc2/common/device/package-info.java
Normal file
@@ -0,0 +1,7 @@
|
||||
@ParametersAreNonnullByDefault
|
||||
@MethodsReturnNonnullByDefault
|
||||
package li.cil.oc2.common.device;
|
||||
|
||||
import mcp.MethodsReturnNonnullByDefault;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
@@ -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());
|
||||
|
||||
@@ -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<String> getTypeNames() {
|
||||
return Collections.singletonList(getClass().getSimpleName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DeviceMethod> getMethods() {
|
||||
return Collections.singletonList(method);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUniqueId() {
|
||||
return UUID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user