fix(world): Chunk-Streaming, Auffangnetz und Schatten folgen dem Fahrzeug
playerCapsule.position ist beim Fahren nicht die Weltposition, sondern der lokale Sitzplatz-Offset (syncMountedPlayer hängt die Kapsel an vehicleGroup und überschreibt ihre .position mit driverSeatPosition * scale). main.js trieb Streaming, isReadyAt, das Auffangnetz, lastSafe und den Schattenwurf trotzdem ausnahmslos damit an — die Welt hörte beim Fahren auf nachzuladen. src/player.js bündelt "wo ist der Spieler gerade" in playerPosition()/ playerIsGrounded(): Fahrzeugposition (vehicleGroup.position) und Radkontakt, wenn eines aktiv ist, sonst Kapsel und das vorhandene getIsOnGround(). Zusätzlich über getControllerMode() abgesichert, nicht nur getActiveVehicle() — Letzteres wird beim Aussteigen vom Controller nie zurückgesetzt (nur destroy() tut das), im Browser nachgewiesen: nach einem erzwungenen Ausstieg lieferte getActiveVehicle() weiterhin das verlassene Fahrzeug, obwohl controllerMode schon wieder 0 war. Im Browser mit von Hand angetriebenem tick()/player.update() verifiziert (die automatisierte Vorschau drosselt requestAnimationFrame auf ~2 Hz): Fahrzeug 227 Einheiten bewegt, playerPosition() folgte exakt, vier neue Chunks luden nach (Netzwerk-Log bestätigt), sichtbar andere Umgebung nach der Fahrt. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
e179794967
commit
b273bb09cc
3 files changed
+193
-6
No files matched your search
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* Einzige Quelle für "wo ist der Spieler gerade" (Befund A, Fix-Runde 3). main.js trieb
|
||||
* Streaming, isReadyAt, Auffangnetz, lastSafe und Schattenwurf an sechs Stellen ausnahmslos
|
||||
* mit player.playerCapsule.position an - das ist falsch, sobald ein Fahrzeug aktiv ist:
|
||||
* PlayerController.syncMountedPlayer() hängt die Kapsel beim Einsteigen als Kind an
|
||||
* vehicle.vehicleGroup und überschreibt cap.position mit driverSeatPosition * scale, einer
|
||||
* festen, kleinen lokalen Zahl nahe dem Ursprung - NICHT der Weltposition. playerCapsule.
|
||||
* position bleibt also beim Fahren nicht etwa nur stehen, es springt auf einen bedeutungslosen
|
||||
* Sitzplatz-Offset. Jede Stelle, die "wo ist der Spieler" braucht, muss über playerPosition()
|
||||
* laufen, sonst hört das Streaming beim Fahren auf nachzuladen.
|
||||
*/
|
||||
/**
|
||||
* getActiveVehicle() allein reicht nicht: VehicleSystem löscht this.active beim Aussteigen
|
||||
* NICHT (weder exit() noch das stopActive(), das reset() bei aktivem Fahrzeug aufruft, setzen
|
||||
* es zurück - nur destroy() tut das, beim kompletten Abbau aller Fahrzeuge). getActiveVehicle()
|
||||
* bleibt also auf dem zuletzt benutzten Fahrzeug stehen, lange nachdem man ausgestiegen ist.
|
||||
* getControllerMode() === 1 ist das einzige verlässliche "fährt gerade wirklich"-Signal (von
|
||||
* enter()/exit() korrekt gesetzt) - per Hand im Browser nachgewiesen: nach reset() bei aktivem
|
||||
* Fahrzeug lieferte getActiveVehicle() weiterhin das verlassene Fahrzeug, obwohl die Kapsel
|
||||
* schon zurück auf dem Spawnpunkt stand und controllerMode schon wieder 0 war.
|
||||
*/
|
||||
function activeVehicleOrNull(player) {
|
||||
return player.getControllerMode() === 1 ? player.getActiveVehicle() : null;
|
||||
}
|
||||
|
||||
export function playerPosition(player) {
|
||||
const vehicle = activeVehicleOrNull(player);
|
||||
return vehicle ? vehicle.vehicleGroup.position : player.playerCapsule.position;
|
||||
}
|
||||
|
||||
/**
|
||||
* Echtes Bodensignal für lastSafe, fahrzeugbewusst (Ruling 52 gilt auch im Auto). Zu Fuß
|
||||
* das vorhandene, raycast-gestützte getIsOnGround(). Im Fahrzeug NICHT dasselbe
|
||||
* getIsOnGround(): controllerMode 1 (Fahrzeug) läuft nie durch CharacterMovement, das
|
||||
* einzige, was playerIsOnGround setzt - der Wert bliebe beim Fahren auf dem Zustand von
|
||||
* kurz vor dem Einsteigen eingefroren (nahezu immer "true", man steigt ja stehend ein) und
|
||||
* würde lastSafe jeden Frame unbesehen überschreiben, auch wenn das Fahrzeug gerade über
|
||||
* einer Klippe oder einer noch nicht geladenen Lücke schwebt - exakt das Verhalten, das
|
||||
* Ruling 52 ("an ein echtes Bodensignal binden statt an die Höhe") verhindern sollte.
|
||||
* Stattdessen derselbe Radkontakt-Test, den VehicleSystem.finishPhysics() intern für
|
||||
* "hasWheelContact" benutzt: mindestens ein Rad mit Bodenkontakt.
|
||||
*/
|
||||
export function playerIsGrounded(player) {
|
||||
const vehicle = activeVehicleOrNull(player);
|
||||
if (!vehicle) return player.getIsOnGround();
|
||||
const wheels = vehicle.vehicleController;
|
||||
for (let i = 0; i < wheels.numWheels(); i++) {
|
||||
if (wheels.wheelIsInContact(i)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Reference in new issue
Block a user