User report: with leader-cam, generation outchased the hero by 10k+ units / 100s of islands. The loop: marbleS ratcheted on the camera subject; the distributed respawn fill places some peers AHEAD of it; a respawned-ahead peer became the new leader, slid the window, culled stragglers respawned (some ahead again) — positive feedback. Now streaming/culling/milestones/respawn-fill all key on marbleS = hero progress only; the camera proxy gets its own path s (camS = followed marble). Peers that reach the built window's forward edge simply run out of rail and respawn behind — self-limiting. Verified: 300 peers, leader-cam, 4 sim-min → 19 segments / 18 islands at hero pace (was 300+ segments / 259 islands); 0 console errors. 116 tests green.
- commit
- 50ebd75285829207194ea4fa3f3cfe25a9ef7225
- parent
- 7a7cede3250050d93f506b09210468eabcd08a17
- author
- Dami <dami.etoile@gmail.com>
| M | src/ | 20 | ++++++++++++++++---- |
@@ -1309,7 +1309,14 @@ class Session {
13091309 }13101310 this.followedIdx = followed.idx;13111311 this.speed = followed.speed;1312- this.marbleS = Math.max(this.marbleS, followed.s);1312+ // The WORLD anchors to the HERO: streaming, culling, milestones and1313+ // respawn fill all key on marbleS = hero progress (ratcheted in the1314+ // hero branch above). The camera subject only moves the lens — with1315+ // leader-cam ratcheting marbleS, a peer respawned into the forward1316+ // fill became the new leader, slid the window, forced stragglers to1317+ // respawn (some ahead again), and generation outchased the hero by1318+ // 10k+ units (user report).1319+ this.camS = followed.s;13131320 // Instanced peers have no scene object — a proxy stands in for the13141321 // camera and the trail.13151322 let fObj: THREE.Object3D;@@ -1328,7 +1335,7 @@ class Session {
13281335 }13291336 if (this.cameraProxy) {13301337 this.cameraProxy.obj = fObj;1331- this.cameraProxy.s = this.marbleS;1338+ this.cameraProxy.s = this.camS;13321339 this.cameraProxy.speed = this.speed;13331340 }13341341 if (this.followedPivot !== fPivot) {@@ -1371,7 +1378,8 @@ class Session {
13711378 // (traffic to catch AND to be caught by).13721379 const span = Math.min(hi - lo, 10 + this.racers.length * 0.35);13731380 const h = (((r.idx * 2654435761) >>> 0) % 1024) / 1024;1374- const at = Math.max(lo, Math.min(hi, this.marbleS + (h - 0.7) * span));1381+ const heroS = this.racers[0]?.s ?? this.marbleS;1382+ const at = Math.max(lo, Math.min(hi, heroS + (h - 0.7) * span));13751383 const seg = this.segmentAt(at);13761384 const rail = seg ? this.rails.get(seg.index) : undefined;13771385 if (!seg || !rail) return;@@ -1624,9 +1632,13 @@ class Session {
16241632 }16251633 | null = null;16261634 1635+ /** Path-parameterized camera s — the followed marble's progress (only1636+ * differs from marbleS under leader-cam). */1637+ private camS = 0;1638+16271639 private syncCameraProxy(): void {16281640 if (!this.cameraProxy) return;1629- this.cameraProxy.s = this.marbleS;1641+ this.cameraProxy.s = this.engine ? this.camS : this.marbleS;16301642 this.cameraProxy.speed = this.speed;16311643 }16321644