feat(editor): F4.6b the command line on a computer's desktop

A new oracle, TerminalWindowRun, types into Java's own command line
window: the window writes each line after its prompt, takes a blank
line, cls, reset and exit itself, keeps the lines for the arrow keys,
and keeps its text, history and working directory over a stop and a
start.

The room now holds a command line window per computer for everyone
(TerminalWindow), kept over stops; the protocol carries its lines and
the one way to read them (terminalScreen); the core goes on in the
working directory of the run before (continueIn). The desktop opens
programs in Java's frame, and the command line works with keyboard and
finger: grey on black, the prompt hidden while a command runs, history,
chips for the commands, Ctrl+C. The room's failure is now tested in the
browser.

Fixed: the room handed the engine the wall clock with fractions of a
millisecond, and a ping hung after its first timeout. The engine and
the room count whole milliseconds, as Java's clock does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-03 14:22:49 +00:00
co-authored by Claude Opus 5.5
parent dfd5ec03ce
commit ac48e969f4
23 changed files with 1255 additions and 47 deletions
@@ -199,6 +199,16 @@ export class Terminal {
return this.directoryValue;
}
/**
* Goes on in the working directory of a run before, where it is still a
* folder: Java's command line keeps it over a stop and a start
* (TerminalWindowRun), and the room's window holds it meanwhile.
*/
continueIn(directory: string): void {
const found = this.content(directory);
if (found !== undefined && found.content.kind === 'directory') this.directoryValue = found.path;
}
/** The window's prompt. */
get prompt(): string {
return `${this.directoryValue}> `;
+3 -2
View File
@@ -1031,7 +1031,7 @@ export class NetworkRuntimeEngine {
this.stateValue = initialState(seed);
this.packetCapture.beginRun();
this.stateValue.phase = 'running';
this.stateValue.currentTimeMilliseconds = input.initialTimeMilliseconds;
this.stateValue.currentTimeMilliseconds = Math.floor(input.initialTimeMilliseconds);
this.stateValue.simulationSpeedPercent = this.runtimeSpeed.percent;
this.stateValue.topologySnapshot = input.snapshot;
this.random = new JavaCompatibleRandom(seed);
@@ -1097,7 +1097,8 @@ export class NetworkRuntimeEngine {
}
case 'advance':
return this.advance(input.toMilliseconds);
// Whole milliseconds, as Java's clock counts (System.currentTimeMillis): a wall clock's fraction waits for the next step.
return this.advance(Math.floor(input.toMilliseconds));
case 'schedule': {
if (this.stateValue.phase !== 'running') return [this.output({ type: 'advanceIgnoredWhileStopped' })];