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 54d625e4..d8ab8126 100644 --- a/src/main/java/li/cil/oc2/api/bus/DeviceBusController.java +++ b/src/main/java/li/cil/oc2/api/bus/DeviceBusController.java @@ -31,17 +31,33 @@ import java.util.UUID; * @see DeviceBusElement */ public interface DeviceBusController { + /** + * Reason for a bus scan. Used to determine whether to immediately perform the scan or no, for example. + */ + enum ScanReason { + BUS_CHANGE, + BUS_ERROR, + } + /** * Schedules a scan. *
- * This will immediately invalidate the current bus, i.e. all {@link DeviceBusElement}s - * will be removed from the controller and {@link #getDevices()} will return an empty - * list after this call. + * Multiple sequential calls to this method do nothing, the actual scan will be performed + * in the next update. + * + * @param reason the reason for the bus scan. + */ + void scheduleBusScan(ScanReason reason); + + /** + * Schedules a scan due to a bus configuration change. *
* Multiple sequential calls to this method do nothing, the actual scan will be performed
* in the next update.
*/
- void scheduleBusScan();
+ default void scheduleBusScan() {
+ scheduleBusScan(ScanReason.BUS_CHANGE);
+ }
/**
* Forces a device map rebuild.
diff --git a/src/main/java/li/cil/oc2/common/bus/CommonDeviceBusController.java b/src/main/java/li/cil/oc2/common/bus/CommonDeviceBusController.java
index 7187638e..f1590fd3 100644
--- a/src/main/java/li/cil/oc2/common/bus/CommonDeviceBusController.java
+++ b/src/main/java/li/cil/oc2/common/bus/CommonDeviceBusController.java
@@ -66,8 +66,10 @@ public class CommonDeviceBusController implements DeviceBusController {
public void dispose() {
for (final DeviceBusElement element : elements) {
element.removeController(this);
+
+ // Let other controllers on the bus know we're gone, so they can quickly recover.
for (final DeviceBusController controller : element.getControllers()) {
- controller.scheduleBusScan();
+ controller.scheduleBusScan(ScanReason.BUS_CHANGE);
}
}
@@ -83,13 +85,15 @@ public class CommonDeviceBusController implements DeviceBusController {
}
@Override
- public void scheduleBusScan() {
- // For multiple controllers, avoid ping-ponging immediate scans when controllers
- // detect each other during their scans.
- if (state != BusState.MULTIPLE_CONTROLLERS) {
- scanDelay = 0; // scan as soon as possible
- state = BusState.SCAN_PENDING;
+ public void scheduleBusScan(final ScanReason reason) {
+ // For notification of a bus error, we just keep our old state and delay, if we have one.
+ // Avoids ping-ponging error states causing scans every tick.
+ if (reason == ScanReason.BUS_ERROR && state.ordinal() < BusState.READY.ordinal()) {
+ return;
}
+
+ scanDelay = 0; // scan as soon as possible
+ state = BusState.SCAN_PENDING;
}
@Override
@@ -172,7 +176,7 @@ public class CommonDeviceBusController implements DeviceBusController {
// Rescan if any bus element gets invalidated. Don't have bus elements keep this instance alive,
// only notify us on change if we still exist.
LazyOptionalUtils.addWeakListener(optionals.get(element), this,
- (controller, ignored) -> controller.scheduleBusScan());
+ (controller, ignored) -> controller.scheduleBusScan(ScanReason.BUS_CHANGE));
}
scanDevices();
@@ -273,6 +277,11 @@ public class CommonDeviceBusController implements DeviceBusController {
for (final DeviceBusElement removedElement : removedElements) {
removedElement.removeController(this);
+
+ // Let other controllers on the bus know we're gone, so they can quickly recover.
+ for (final DeviceBusController controller : removedElement.getControllers()) {
+ controller.scheduleBusScan(ScanReason.BUS_CHANGE);
+ }
}
final HashSet