Ruling 51: #load() rief addCollider() auch für Chunks ohne jede Kollisions-
geometrie auf (offenes Wasser: 4_6, 4_10, 5_6, 5_10 — an den Rohdaten
nachgezählt). Das lieferte nur eine Fremdwarnung aus ColliderRegistry und
ein handle mit id:-1, das nie ready wird. addCollider läuft jetzt nur noch,
wenn die collide-Gruppe Kinder hat; #unload und isReadyAt behandeln einen
Eintrag ohne handle korrekt (kein removeCollider nötig, sofort "bereit").
Ruling 52: lastSafe hielt sich an der Höhe fest (p.y > -1), nicht am
tatsächlichen Bodenkontakt — der Scheitel eines Sprungs oder ein Dach
zählten als "sicher". Prüfung im Submodul ergab: playerIsOnGround (public,
via setOnGround() nur aus snapToGround() auf true gesetzt) mit passendem
Getter getIsOnGround(). lastSafe aktualisiert sich jetzt nur noch bei
echtem Bodenkontakt.
Ruling 53: setSkipCapsuleCollision(true) schaltet nur die horizontale
Kollision ab, applyGravity läuft unabhängig weiter — die "Schwebephase"
war freier Fall. Die alte 15s-Zeitschranke schaltete die Kollision ohne
vorhandenen Boden scharf, was bei dauerhaft fehlendem Chunk in eine
endlose Fall-Auffang-Schleife lief. Die Figur wird jetzt aktiv auf
Spawnhöhe gehalten, bis ihr Chunk bereit ist; nach 15s nur noch eine
einmalige Warnung, kein Verhaltenswechsel. Per künstlicher 8s-Verzögerung
gemessen: Höhe blieb über den gesamten (durch Worker-Pool-Stau auf über
14s verlängerten) Wartezeitraum innerhalb 0,004 Einheiten der Spawnhöhe.
Neue Tests in tests/streaming.test.js decken Ruling 51 ab (ChunkStreamer
mit gemocktem fetch/player/scene); Ruling 52/53 sind Physik-Verhalten des
Submoduls und über den Browser verifiziert (Bericht: task-8-report.md).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
wantedChunks() liefert Lade-/Entladelisten mit Hysterese (Laderadius 400,
Entladeradius 600) um die Spielerposition; ChunkStreamer holt Chunks per
fetch, baut sie über buildChunkGeometry() (Task 7) zu Meshes, registriert
die Kollisionsschicht (ground/bridges/buildings) beim Player-Controller
mit asynchronem BVH-Bau und meldet über isReadyAt() wann ein Collider
tatsächlich einsatzbereit ist. Straßen/Sand/Park/Stadtfläche bleiben reine
Auflagen ohne eigene Kollision.
main.js schwebt die Figur kollisionsfrei am Spawn (Vice Beach), bis ihr
Chunk bereit ist oder 15s vergangen sind, und fängt jeden tieferen
Durchfall über ein Auffangnetz ab, das zur letzten sicheren Höhe
zurücksetzt. Der alte Platzhalter-Boden (400x400-Ebene samt Collider)
entfällt zugunsten der echten gestreamten Welt.
Der zweite Testfall aus dem Task-Brief hatte einen Datenfehler: die
"near"-Position {x:1375,z:-1375} traf exakt das Zentrum von Chunk 9_4
(Distanz zu Chunk 5_5 ca. 1030, weit jenseits des Entladeradius 600) und
ließ die eigene Behauptung "not.toContain" fehlschlagen, sobald
streaming.js existierte (RED belegt im Task-8-Report). Position auf
{x:875,z:-1125} korrigiert, exakt 500 Einheiten von Chunk 5_5 entfernt —
außerhalb von 400, innerhalb von 600 — und damit die Hysterese, die der
Testname behauptet.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>