Race : la transition au niveau suivant téléporte au coin au lieu du checkpoint de l'area

Symptôme

Dans la fonctionnalité race (multi-niveaux), quand un joueur franchit l'exit teleporter d'un niveau, il doit atterrir sur le checkpoint de l'area du niveau suivant — le même point que celui utilisé au départ du niveau 1 et à la reprise après reconnexion. Or il est téléporté au coin du niveau (min corner), pas au checkpoint.

Deux cas reproduits en jeu :

  1. Race générée sans aucune retouche → la transition niveau→niveau dépose le joueur au coin.
  2. Après modification du checkpoint de l'area générée via le menu area configuration → la transition dépose toujours au coin (le nouveau checkpoint est ignoré).

En revanche, le départ du niveau 1 fonctionne (le joueur arrive au bon checkpoint), ce qui prouve que les areas de race possèdent bien un checkpoint correct en base.

Cause racine

Tous les points de téléportation de la race utilisent RaceResumeService.resolveCheckpoint(ref) (qui lit area.getAreaCheckpointLocation(), avec repli sur le coin) — sauf la transition niveau→niveau.

RaceTransitionService.handleMidRace() calcule la destination via copyLayout.levels().get(nextLevelIndex).entranceLocation(). Cette valeur est calculée par LayoutService.computeLayout() comme levelOrigin + schematic.getCheckpointX/Y/Z() ; elle vaut le coin (offsets nuls) et ignore toute modification de checkpoint faite via le menu area configuration (qui n'écrit que sur l'area en base, lue uniquement par resolveCheckpoint).

La transition est donc le seul chemin qui court-circuite la source de vérité du checkpoint.

Correctif proposé

Aligner la transition mid-race sur exactement le même mécanisme que le départ niveau 1 et la reprise : lire le checkpoint de l'area du niveau suivant via resolveCheckpoint, avec repli sur entranceLocation() si aucun RaceAreaRef n'est trouvé (edge-case monde déchargé) → aucune régression.

Périmètre : une seule méthode modifiée (RaceTransitionService.handleMidRace()). Pas de changement de schéma, de DB ni de nouvelle classe. entranceLocation reste utilisé ailleurs (réplication, inventaire builder) et n'est pas touché.