mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-11-11 19:03:03 +00:00
Don't propagate redstone when blink/label changes
Historically, computers tracked whether any world-visible state (on/off/blinking, label and redstone outputs) had changed with a single "has changed" flag. While this is simple to use, this has the curious side effect of that term.setCursorBlink() or os.setComputerLabel() would cause a block update! This isn't really a problem in practice - it just means slightly more block updates. However, the redstone propagation sometimes causes the computer to invalidate/recheck peripherals, which masks several other (yet unfixed) bugs.
This commit is contained in:
@@ -15,8 +15,7 @@ import dan200.computercraft.core.filesystem.FileSystem;
|
||||
import dan200.computercraft.core.terminal.Terminal;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
@@ -54,9 +53,9 @@ public class Computer {
|
||||
private final AtomicLong lastTaskId = new AtomicLong();
|
||||
|
||||
// Additional state about the computer and its environment.
|
||||
private boolean blinking = false;
|
||||
private final Environment internalEnvironment;
|
||||
private final AtomicBoolean externalOutputChanged = new AtomicBoolean();
|
||||
|
||||
private final AtomicInteger externalOutputChanges = new AtomicInteger();
|
||||
|
||||
private boolean startRequested;
|
||||
private int ticksSinceStart = -1;
|
||||
@@ -140,10 +139,7 @@ public class Computer {
|
||||
}
|
||||
|
||||
public void setLabel(@Nullable String label) {
|
||||
if (!Objects.equals(label, this.label)) {
|
||||
this.label = label;
|
||||
externalOutputChanged.set(true);
|
||||
}
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
@@ -164,28 +160,24 @@ public class Computer {
|
||||
internalEnvironment.tick();
|
||||
|
||||
// Propagate the environment's output to the world.
|
||||
if (internalEnvironment.updateOutput()) externalOutputChanged.set(true);
|
||||
|
||||
// Set output changed if the terminal has changed from blinking to not
|
||||
var blinking = terminal.getCursorBlink() &&
|
||||
terminal.getCursorX() >= 0 && terminal.getCursorX() < terminal.getWidth() &&
|
||||
terminal.getCursorY() >= 0 && terminal.getCursorY() < terminal.getHeight();
|
||||
if (blinking != this.blinking) {
|
||||
this.blinking = blinking;
|
||||
externalOutputChanged.set(true);
|
||||
}
|
||||
externalOutputChanges.accumulateAndGet(internalEnvironment.updateOutput(), (x, y) -> x | y);
|
||||
}
|
||||
|
||||
void markChanged() {
|
||||
externalOutputChanged.set(true);
|
||||
}
|
||||
|
||||
public boolean pollAndResetChanged() {
|
||||
return externalOutputChanged.getAndSet(false);
|
||||
/**
|
||||
* Get a bitmask returning which sides on the computer have changed, resetting the internal state.
|
||||
*
|
||||
* @return What sides on the computer have changed.
|
||||
*/
|
||||
public int pollAndResetChanges() {
|
||||
return externalOutputChanges.getAndSet(0);
|
||||
}
|
||||
|
||||
public boolean isBlinking() {
|
||||
return isOn() && blinking;
|
||||
if (!isOn() || !terminal.getCursorBlink()) return false;
|
||||
|
||||
var cursorX = terminal.getCursorX();
|
||||
var cursorY = terminal.getCursorY();
|
||||
return cursorX >= 0 && cursorX < terminal.getWidth() && cursorY >= 0 && cursorY < terminal.getHeight();
|
||||
}
|
||||
|
||||
public void addApi(ILuaAPI api) {
|
||||
|
||||
@@ -411,7 +411,6 @@ final class ComputerExecutor implements ComputerScheduler.Worker {
|
||||
|
||||
// Initialisation has finished, so let's mark ourselves as on.
|
||||
isOn = true;
|
||||
computer.markChanged();
|
||||
} finally {
|
||||
isOnLock.unlock();
|
||||
}
|
||||
@@ -446,7 +445,6 @@ final class ComputerExecutor implements ComputerScheduler.Worker {
|
||||
}
|
||||
|
||||
computer.getEnvironment().resetOutput();
|
||||
computer.markChanged();
|
||||
} finally {
|
||||
isOnLock.unlock();
|
||||
}
|
||||
|
||||
@@ -222,22 +222,22 @@ public final class Environment implements IAPIEnvironment {
|
||||
*
|
||||
* @return If the outputs have changed.
|
||||
*/
|
||||
boolean updateOutput() {
|
||||
int updateOutput() {
|
||||
// Mark output as changed if the internal redstone has changed
|
||||
synchronized (internalOutput) {
|
||||
if (!internalOutputChanged) return false;
|
||||
if (!internalOutputChanged) return 0;
|
||||
|
||||
var changed = false;
|
||||
var changed = 0;
|
||||
|
||||
for (var i = 0; i < ComputerSide.COUNT; i++) {
|
||||
if (externalOutput[i] != internalOutput[i]) {
|
||||
externalOutput[i] = internalOutput[i];
|
||||
changed = true;
|
||||
changed |= 1 << i;
|
||||
}
|
||||
|
||||
if (externalBundledOutput[i] != internalBundledOutput[i]) {
|
||||
externalBundledOutput[i] = internalBundledOutput[i];
|
||||
changed = true;
|
||||
changed |= 1 << i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user