feat(vessels): key vessels by their source's stable id, and share a selected vessel

AIS Vessels are keyed by the id their live source gives, with the MMSI as an
attribute: an MMSI can be shared, spoofed or reused, so two vessels with one
MMSI are now two vessels. Looking a vessel up or selecting it by MMSI still
finds it.

A share link made while a vessel is selected opens that vessel. A UUID vessel
id travels as 16 bytes in a new thing field (13). A shared thing that is not
reporting now says so in a sentence per kind, with its id (ICAO, NORAD, MMSI
or vessel UUID) on a second line.
This commit is contained in:
Sameh Khamis committed 2026-11-10 18:12:53 -08:00
1 parent 57ff81f723
commit cbbf55cacd
74 files changed
+2481 -586

No files matched your search

+5 -3
View File
@@ -83,8 +83,10 @@ export function onScenePointerDown(nowMs = performance.now()) {
return;
}
const at = subjectCanvasPosition.call(this);
const mmsi = this.readVesselInfo()?.mmsi ?? null;
this.doubleClickStart = at ? { x: at.x, y: at.y, atMs: nowMs, mmsi } : null;
const vesselId = this.readVesselInfo()?.id ?? null;
this.doubleClickStart = at
? { x: at.x, y: at.y, atMs: nowMs, vesselId }
: null;
}
/**
@@ -111,7 +113,7 @@ export function onSceneDoubleClick(position, nowMs = performance.now()) {
// The memory is the ship's it was taken for: one followed since (an
// aircraft, another ship) is hit only where it is drawn.
this.resolveEntryKind() === 'vessel' &&
start.mmsi === (this.readVesselInfo()?.mmsi ?? null) &&
start.vesselId === (this.readVesselInfo()?.id ?? null) &&
doubleClickHitsSubject(position, start));
if (!hit) return false;
this.enter();