mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-15 07:42:23 +00:00
fix(cockpit): a coarse read never takes a river bridge back to the sea
Before the first full-detail water read lands (it can take many seconds from cold tiles), a refresh's loaded-tile read with one low probe still dropped a river height to the geoid. Before that landing, loaded-tile reads may now find raised water but only a full-detail read lowers it. CURRENT-STATE also says what the earlier fixes changed: C stays the CCTV shortcut when the bridge cannot be entered, voice entry is refused on a bridge, and the ridden ship's trail is hidden with its sprite.
This commit is contained in:
1 parent
5c937e67e1
commit
80a33ba52c
3 files changed
+44
-9
No files matched your search
+10
-5
@@ -1530,16 +1530,20 @@ With no aircraft tracked, Cockpit can ride the selected AIS vessel instead.
|
|||||||
Entry needs only the layer of the vessel it rides, Live AIS Vessels, and a
|
Entry needs only the layer of the vessel it rides, Live AIS Vessels, and a
|
||||||
selected vessel; Contacts and every other layer may be off, before or during
|
selected vessel; Contacts and every other layer may be off, before or during
|
||||||
the bridge (`bridgeEntryAllowed` in `src/contextModePolicy.js`). A Context mode
|
the bridge (`bridgeEntryAllowed` in `src/contextModePolicy.js`). A Context mode
|
||||||
change still in flight blocks entry until it settles. `C` enters it, and the
|
change still in flight blocks entry until it settles. `C` enters it (when
|
||||||
|
the bridge cannot be entered, `C` stays the CCTV shortcut), and the
|
||||||
entry button reads BRIDGE with a ship icon both in Contacts (`#cockpit-entry`)
|
entry button reads BRIDGE with a ship icon both in Contacts (`#cockpit-entry`)
|
||||||
and under the selected vessel's Intel HUD readout in the bottom-right corner
|
and under the selected vessel's Intel HUD readout in the bottom-right corner
|
||||||
(`#cockpit-entry-readout`, shown with the HUD on, in its Tactical and Cyber
|
(`#cockpit-entry-readout`, shown with the HUD on, in its Tactical and Cyber
|
||||||
layouts). Turning Live AIS Vessels off ends the bridge: the layer then has no
|
layouts). Turning Live AIS Vessels off ends the bridge: the layer then has no
|
||||||
subject (`getCockpitSubject` returns null). The bridge picture uses AIS alone,
|
subject (`getCockpitSubject` returns null). The bridge picture uses AIS alone,
|
||||||
so no other feed being off makes it partial.
|
so no other feed being off makes it partial.
|
||||||
Voice (`control_cockpit`) and the selection entry transaction stay aircraft-only.
|
Voice (`control_cockpit`) and the selection entry transaction stay aircraft-only;
|
||||||
|
voice `enter` on a bridge is refused before it touches tracking, with the
|
||||||
|
reason to exit the bridge first.
|
||||||
The vessel layer supplies the subject (`getCockpitSubject`), hides that ship's
|
The vessel layer supplies the subject (`getCockpitSubject`), hides that ship's
|
||||||
sprite, card and detection bracket while it is held (`setCockpitSubject`), and
|
sprite, card, detection bracket and trail while it is held
|
||||||
|
(`setCockpitSubject`), and
|
||||||
ignores scene clicks so open water cannot deselect it. The eye sits on the AIS
|
ignores scene clicks so open water cannot deselect it. The eye sits on the AIS
|
||||||
position at a representative bridge height for the AIS type family
|
position at a representative bridge height for the AIS type family
|
||||||
(`src/layers/vessels/cockpitSubject.js`: cargo and tanker 30 m, passenger 25 m,
|
(`src/layers/vessels/cockpitSubject.js`: cargo and tanker 30 m, passenger 25 m,
|
||||||
@@ -1569,8 +1573,9 @@ eight probes 30 m out, the lowest probe taken as the water when it is 2 m to
|
|||||||
the full-detail read replaces it; it repeats every 5 s. Only one full-detail
|
the full-detail read replaces it; it repeats every 5 s. Only one full-detail
|
||||||
read runs at a time: while one is still running, a refresh reads the loaded
|
read runs at a time: while one is still running, a refresh reads the loaded
|
||||||
tiles instead, and the slow read applies whenever it lands. Once a
|
tiles instead, and the slow read applies whenever it lands. Once a
|
||||||
full-detail read has answered, loaded-tile reads no longer change the height,
|
full-detail read has answered, loaded-tile reads no longer change the height;
|
||||||
and a read that sampled nothing keeps the height it had. A failed read keeps
|
before then they may find raised water but never take it back to the sea.
|
||||||
|
A read that sampled nothing keeps the height it had. A failed read keeps
|
||||||
the sea surface.
|
the sea surface.
|
||||||
|
|
||||||
The HUD keeps its frame, vision styles, briefing, weather and Display/Radio
|
The HUD keeps its frame, vision styles, briefing, weather and Display/Radio
|
||||||
|
|||||||
@@ -1350,6 +1350,30 @@ test('a river height stands through reads that sample nothing or one coarse prob
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('before any full read lands, a coarse loaded read keeps the river it found', async (t) => {
|
||||||
|
const clock = manualClock(t, START_MS);
|
||||||
|
const sea = await bridgeAt(t, clock);
|
||||||
|
frames(sea.cockpit, clock, sea.shots, 60);
|
||||||
|
const seaEyeM = eyeHeightM(sea.shots.at(-1));
|
||||||
|
sea.cockpit.exit();
|
||||||
|
|
||||||
|
clock.set(START_MS);
|
||||||
|
const record = { ...RECORD, lastPositionEpoch: START_MS / 1000 };
|
||||||
|
const ship = fixture(t, { record });
|
||||||
|
// The full-detail read is cold and never lands in this test.
|
||||||
|
ship.viewer.scene.sampleHeightMostDetailed = () => new Promise(() => {});
|
||||||
|
ship.viewer.scene.sampleHeight = () => 27;
|
||||||
|
ship.cockpit.enter();
|
||||||
|
await settle();
|
||||||
|
ship.cockpit.update();
|
||||||
|
frames(ship.cockpit, clock, ship.shots, 60);
|
||||||
|
near(eyeHeightM(ship.shots.at(-1)) - seaEyeM, 27, 'on the river', 0.5);
|
||||||
|
// A refresh meets one low probe on coarse tiles.
|
||||||
|
ship.viewer.scene.sampleHeight = () => 0.5;
|
||||||
|
frames(ship.cockpit, clock, ship.shots, 240);
|
||||||
|
near(eyeHeightM(ship.shots.at(-1)) - seaEyeM, 27, 'still on the river', 0.5);
|
||||||
|
});
|
||||||
|
|
||||||
test('a client clock minutes fast does not age the bridge into a stale feed', async (t) => {
|
test('a client clock minutes fast does not age the bridge into a stale feed', async (t) => {
|
||||||
// The feed's newest fix is this ship's; the client clock runs 200 s
|
// The feed's newest fix is this ship's; the client clock runs 200 s
|
||||||
// ahead of the feed and received the refresh just now.
|
// ahead of the feed and received the refresh just now.
|
||||||
|
|||||||
+10
-4
@@ -110,9 +110,10 @@ export function update() {
|
|||||||
* every frame until it settles): while one is still running, a refresh
|
* every frame until it settles): while one is still running, a refresh
|
||||||
* reads the loaded tiles instead, and the slow read applies whenever it
|
* reads the loaded tiles instead, and the slow read applies whenever it
|
||||||
* lands. Once a full-detail read has answered, only full-detail reads
|
* lands. Once a full-detail read has answered, only full-detail reads
|
||||||
* change the height: a loaded-tile read stands in only until the first
|
* change the height; before then a loaded-tile read may find raised water
|
||||||
* lands, so one coarse probe cannot drop a river bridge to the sea, and a
|
* but never takes a raised height back to the sea. One coarse probe cannot
|
||||||
* read that sampled nothing keeps the height it had.
|
* drop a river bridge to the sea, and a read that sampled nothing keeps
|
||||||
|
* the height it had.
|
||||||
* @param {{latitude: number, longitude: number}} [at] Where to read the
|
* @param {{latitude: number, longitude: number}} [at] Where to read the
|
||||||
* water: the dead-reckoned position the camera rides.
|
* water: the dead-reckoned position the camera rides.
|
||||||
* @returns {number} Ellipsoidal metres.
|
* @returns {number} Ellipsoidal metres.
|
||||||
@@ -145,7 +146,12 @@ function vesselSurfaceM(info, nowMs, at = info) {
|
|||||||
read.sampledMs = nowMs;
|
read.sampledMs = nowMs;
|
||||||
if (read.inFlight && !read.landed) {
|
if (read.inFlight && !read.landed) {
|
||||||
const loadedM = loadedWaterlineM(scene, probes, seaM);
|
const loadedM = loadedWaterlineM(scene, probes, seaM);
|
||||||
if (Number.isFinite(loadedM)) read.heightM = loadedM;
|
// Taking a river back to the sea is the full-detail read's to say.
|
||||||
|
const lowers =
|
||||||
|
Number.isFinite(read.heightM) &&
|
||||||
|
read.heightM > seaM &&
|
||||||
|
!(loadedM > seaM);
|
||||||
|
if (Number.isFinite(loadedM) && !lowers) read.heightM = loadedM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!read.inFlight) readWaterline.call(this, read, scene, probes, seaM);
|
if (!read.inFlight) readWaterline.call(this, read, scene, probes, seaM);
|
||||||
|
|||||||
Reference in new issue
Block a user