Skip to content

Releases: lionrayonnant/FPVThePlanet

v1.2.0

Choose a tag to compare

@github-actions github-actions released this 23 Sep 22:14
800657f

Ajouté

  • La nomenclature devient vérifiable. Chaque famille nomme désormais son
    moteur, son hélice et son pack par leur identifiant de catalogue
    (motor.part, propPart, battery.part), et profile-schema-selftest
    refuse une référence qui ne résout pas, un KV qui contredit son entrée, une
    diagonale d'hélice ou un pas qui ne sont pas ceux du catalogue. Le 2207 à
    2450 KV de la référence — la dernière référence du fichier qui n'était pas un
    fait — est déclaré dans OFF_CATALOGUE_MOTORS avec sa provenance, pas
    dans SPEC_MOTORS : ce catalogue est une transcription dont le nombre
    d'entrées est épinglé, et y ajouter une ligne serait exactement ce que cette
    vérification existe pour attraper. Rien ne bouge en vol : freestyle5 reste
    la référence au bit près.
  • BENCH : la machine exacte (#159). L'aéronef du banc n'est plus un menu
    déroulant sur six familles, c'est un montage. Une BASE — NOMINAL, un
    exemplaire tiré (INDIVIDUAL), ou CUSTOM, assemblé depuis le catalogue de
    la spec (21 moteurs, 20 hélices, 13 châssis, 17 packs, 3 caméras) — et,
    par-dessus, 45 paramètres réglables au chiffre près : masse, inerties, bras,
    hélice, moteur, pack, traînée, PID, rates, courbe de gaz, bruit gyro, latence
    de boucle. La dérivation CUSTOM n'invente rien : elle applique les quatre
    règles déjà écrites en tête de drone-profiles.js. NOMINAL sans réglage
    reste exactement le profil de référence — la fonctionnalité est inerte
    tant qu'on n'y touche pas.
  • La radio se règle en vol, au banc (#159). ON AIR, le pool, le morceau et
    le transport dans le panneau de vol du banc : le jukebox continuait de jouer
    après qu'on en sortait, mais plus rien n'y donnait accès une fois en l'air.
    Au banc seulement — en FIELD la musique est l'arc de la Bible §34.

Modifié

  • Le nombre de vérifications n'est plus annoncé à trois endroits
    différents.
    README.md disait « 2 700+ », docs/manual.md « ~1 430 »,
    CONTRIBUTING.md « environ 1 200 » : trois chiffres pour une seule chaîne.
    Le manuel le porte seul, mesuré (~3 200), avec la commande qui le recompte.
    Le manuel gagne au passage la liste complète des scripts de
    sim/package.json — electron, sync-scenes, resume, replay,
    validate:props et les autres n'y figuraient nulle part.
  • package-lock.json est réindenté en tabulations, celles que npm réécrit
    en lisant package.json : chaque npm install laissait sinon un diff de
    5 983 lignes dans l'arbre de travail. Aucune dépendance ne change.
  • CLAUDE.md, HANDOFF.md et docs/PICKUP.md cessent de décrire un dépôt
    privé et une branche non fusionnée.
    Le passage au public est fait des deux
    côtés qu'il annonçait (provider: github, jeton de déploiement facultatif),
    et le lot « gravité » est sur main.
  • propInertia est dérivé au lieu d'être choisi. Normalisé en
    k = I / (m * R^2), le fichier impliquait un k de 0,115 à 0,620 sur sept
    pièces qui sont le même objet moulé à des tailles différentes. Une hélice est
    géométriquement auto-similaire : pales effilées portant leur masse en dedans,
    sur un moyeu à rayon quasi nul. La tige uniforme donne 1/3, l'effilement et
    le moyeu ramènent dans 0,2–0,3, et la référence mesure 0,248 — c'est la
    constante, et la masse vient du catalogue. Le nombre de pales n'entre pas, et
    c'est un résultat : 4 g pour un 5", 7 g pour un 6" et 2 g pour un 3" sont des
    masses de tripale et ces familles volent en tripale ; 8 g pour un 7" et 1 g
    pour un 2,5" sont des masses de bipale (un 7" tripale pèse 11-12 g) et ces
    familles volent en bipale. Chaque masse du catalogue est déjà celle de
    l'hélice embarquée. Corrections : cinewhoop −60 %, toothpick −17 %, race5
    +11 %, swarmNode +46 %, longrange +115 % — cette dernière parce que son
    commentaire comptait le nombre de pales deux fois, en partant d'un 1,1e-5
    deviné pour un 7" tripale puis en le multipliant par 2/3, alors que les 8 g du
    catalogue sont déjà la bipale. freestyle5 et heavy5 ne bougent pas d'un
    bit, les six séquences de npm run replay le confirment.
  • L'inertie de swarmNode est reconstruite à partir de ses pièces. Elle
    était « heavy5 mise à l'échelle, interpolée vers longrange », et longrange a
    bougé sous elle (0,92 → 1,05 kg, tripale → bipale de catalogue, inertie
    refaite). Une interpolation ne vaut que ses extrémités : elle est remplacée
    par le modèle que longrange documente — quatre masses ponctuelles aux coins
    plus une boîte équivalente calibrée sur freestyle5 —, qui reproduit ses deux
    points de calibration à 0,3 %. Résultat 11 à 13 % plus bas, et un rapport
    I_lacet/(I_tangage+I_roulis) de 0,942 qui la remet dans la bande où sont les
    six autres au lieu de 0,920 toute seule. Le départ connu est écrit : ~170 g de
    radio maillée sont au mât, au-dessus du centre de masse, et la boîte les
    répartit.
  • Les six réglages PID sont rebalayés, plus celui de swarmNode, contre les
    nouvelles inerties. freestyle5 et heavy5 en ressortent identiques.

Corrigé

  • Les réglages audio ne prenaient effet qu'au hack suivant. Les trois
    curseurs (Volume, Tone, Music) n'étaient branchés sur le son qu'au démarrage
    d'une scène (finishBoot) : ouverts depuis le terminal, ils écrivaient le
    localStorage et leur libellé, et rien d'autre. Le branchement se fait
    désormais une seule fois, au chargement du module. Et il ne suffisait pas :
    audio-bus.js ignorait un volume demandé avant l'existence du contexte audio
    — il le mémorise maintenant et construit son graphe à cette valeur.

  • Trois indications du HUD pointaient à l'envers. Après prep, les
    coordonnées sont en mètres ENU locaux avec Z = sud : le nord est -Z, et
    chaque relèvement porte un signe moins facile à perdre. Trois lectures
    l'avaient perdu, chacune à sa façon. La flèche HOME calculait
    atan2(dx, dz) : le point de départ droit devant était dessiné droit
    derrière — gauche et droite sortant justes, personne ne l'avait vu. Le ruban
    de cap publiait le lacet du quaternion, qui est l'opposé du cap : nez à
    l'est, il affichait 270 ; le headingDeg de la piste, donc le cap stocké avec
    chaque photo, portait la même inversion. La flèche de vent du HUD, elle,
    inversait gauche et droite : un vent de travers venant de gauche était dessiné
    comme poussant vers la gauche. Les trois sites faisaient chacun leur propre
    trigonométrie ; src/bearing.js la tient désormais seul, et
    tools/bearing-selftest.mjs épingle les cas tels que le pilote les voit.

  • Le compteur DECODING de l'écran de chargement pouvait passer sous zéro.
    Incrémenté sur le seul message stage: 'decoding', il était décrémenté sur
    tout message terminal — y compris l'échec qu'un worker renvoie quand son
    téléchargement a échoué avant tout décodage. Une planche en 404 et l'écran
    affichait « DECODING -1 SHEET(S) ».

  • Un chunk en échec abandonnait ses voisins. Le chargement entier était
    rejeté, mais les deux autres workers continuaient de décoder (~135 Mo chacun)
    vers une scène que personne ne monterait, et les matières déjà poussées dans
    tileMaterials n'étaient jamais rendues : dispose() libère le GPU, pas le
    tampon de pixels JS. Un chargement qui échoue arrête maintenant ses voisins et
    rend ce qu'il a construit.

  • Quitter une acquisition laissait fuir son minuteur de silence. LEAVE
    arrêtait l'horloge, la RTC et le flux SSE, mais pas le minuteur que finish()
    nettoie — et celui-ci écrit dans .sc-job-note, résolu contre le panneau
    monté au moment où il se déclenche. Partir dans les dix secondes puis lancer
    une autre acquisition faisait écrire « LINK INTERRUPTED » par-dessus le
    nouveau travail, en bonne santé.

  • Le pied d'une colonne nulle passait sous l'axe dans l'onglet DATA
    (Math.max(..., v > 0 ? 1 : 1) contre un sommet planché à 0), et la grille de
    repli d'entry-state.js annonçait un cellSize lu sur les cellules de la
    grille au lieu de son propre pavé.

  • La convention de battery.maxCurrent est tranchée et épinglée. Le champ
    est documenté « A aux quatre moteurs plein gaz », donc le tirage du build ;
    la note du pack, elle, vaut capacité * C — pour le 4s-1300 de la
    référence, 195 A contre les 100 A du tirage. Les deux nombres sont vrais et ne
    sont pas la même grandeur, et c'est cette ambiguïté qui faisait passer le
    champ pour incohérent. La règle 3 du fichier donne le tirage, les sept
    familles la respectent à mieux que 1 %, et un test le vérifie — avec un second
    qui compare au plafond du pack. À savoir en le lisant : aucune physique ne
    lit maxCurrent
    , le pack s'affaisse sur le vrai courant de bobinage issu de
    la balance de couple de motor.js. C'est un chiffre de fiche technique, ce
    qui est précisément pourquoi il lui faut un test et pas un lecteur.

Ajouté

  • ?aero=bem : l'hélice en théorie de l'élément de pale, éteinte par
    défaut.
    src/blade-element.js existait, validé sur 187 hélices de
    soufflerie, et n'était branché nulle part : le câbler remplace le modèle de
    poussée et invalide six réglages sur la foi d'un terme edgewise qu'aucun banc
    d'ici ne peut vérifier — la soufflerie UIUC souffle dans l'axe. Il est donc
    câblé derrière un drapeau, plombé comme ?loop=, et le chemin par défaut est
    identique au bit près : cmp ne trouve pas un octet d'écart sur les 36
    traces de npm run replay, et un selftest compare 400 pas élément par élément
    entre le défaut, aero:'classic' explicite et un drapeau inconnu. Ce que le
    drapeau achète, c'est que le terme edgewise devienne mesurable à défaut
    d'être vérifiable : tools/aero-model-compare.mjs met les deux modèles côte à
    côte — poussée, couple et force en plan, du stationnaire à la croisière, plus
    la garde de #103 jouée contre les deux. Ce qu'il dit : la lame rend 14 à 30 %
    de poussée en moins au stationnaire, et tout cet écart est `pr...
Read more

v1.1.0

Choose a tag to compare

@github-actions github-actions released this 13 Sep 15:30

Ce que la première mise en ligne réelle a trouvé. La 1.0.0 a été taguée avant
qu'une instance publique existe : tout ce qui suit a été découvert en la
déployant pour de bon, et rien de tout cela ne pouvait l'être autrement.

Corrigé

  • Le curseur disparaissait dès qu'un clic tombait à côté d'un bouton. Le
    curseur EST le focus natif du navigateur : cliquer sur le fond d'un écran, un
    titre ou une ligne de texte le fait perdre, plus rien ne porte le marqueur ▌
    et Entrée n'active plus rien. Il fallait une flèche — qui repartait du haut de
    la liste — ou Échap pour ressortir et revenir. Le focus est désormais reposé
    là où il était
    , sur focusout plutôt qu'en bloquant le mousedown : la
    sélection à la souris reste possible, et on sélectionne à la main dans ces
    écrans (une adresse de paiement, une ligne de journal). Sortir d'un champ de
    saisie reste une intention : le curseur repart alors du premier contrôle sur
    lequel on peut appuyer, sans y être renvoyé.

    Deux déclencheurs, parce qu'un seul navigateur ne suffit pas à prouver un
    correctif de focus : Chrome ne déplace le focus qu'une fois, au mousedown,
    et focusout y suffisait ; Firefox défocalise au mousedown PUIS
    réattribue le focus à la fin du clic — le rétablissement, différé d'un tour,
    tombait entre les deux et le clic le défaisait. L'écouteur click, qui passe
    après toute la séquence souris, est celui qui tient dans cet ordre-là. Les
    deux sont sans effet quand le focus est déjà quelque part dans l'écran.

  • JUKEBOX, onglet ALL : les lignes étaient écrasées à 6,5 px. Les 143
    morceaux étaient bien là, dans l'ordre, avec le bon texte, et aucun n'était
    lisible. Un flex-direction: column avec un max-height ne déborde pas dans
    sa barre de défilement : par défaut il rétrécit ses enfants jusqu'à ce que
    tout rentre. En dessous d'une vingtaine d'éléments rien ne bouge — d'où un
    filtre par pool parfait et un seul onglet cassé. La même forme existait quatre
    fois (les deux listes, le panneau des réglages, la page DATA) ;
    tools/list-layout-selftest.mjs refuse désormais une cinquième qui
    l'oublierait.

  • La carte de l'onglet LIVE ne s'affichait plus : toutes les tuiles
    OpenStreetMap revenaient en 403 « Access blocked ». L'en-tête
    Referrer-Policy: no-referrer, ajouté par la passe de sécurité de la 1.0.0,
    retirait le Referer des requêtes de tuiles — or la politique d'usage d'OSM
    exige un Referer ou un User-Agent qui identifie l'application, et un
    navigateur n'envoie qu'un User-Agent générique. Remplacé par
    strict-origin-when-cross-origin, qui garde l'intention : le même-origine
    conserve l'URL complète, donc le slug de scène et la graine de build ne
    sortent toujours pas, et OSM reçoit l'origine nue dont il a besoin.

    Invisible en développement, parce que Vite ne sert aucun de ces en-têtes :
    seule une vraie mise en production pouvait le montrer. Concerne aussi les
    applications de bureau 1.0.0
    , qui embarquent le même serveur.

  • deploy.sh téléchargeait les métadonnées JSON de l'asset au lieu de
    l'archive, et tar échouait sur « not in gzip format ». gh_api pose
    Accept: application/vnd.github+json et la fonction de téléchargement en
    ajoutait un second en application/octet-stream : curl envoie les deux,
    GitHub honore le premier. Le script passe maintenant par
    browser_download_url, qui sert les octets sans négociation de contenu —
    possible parce que le dépôt est public. Il vérifie en plus que le fichier
    reçu est bien une archive, et affiche ses premiers octets sinon.

  • Caddy journalise vers journald au lieu d'un fichier. output file imposait
    de créer /var/log/caddy à la main, entre deux étapes précises, et refusait
    quand même de démarrer le service alors que le répertoire appartenait bien à
    caddy et y était inscriptible. Une ligne de configuration pour un mode de
    panne spécifique à la plateforme : journalctl -u caddy -f donne les mêmes
    accès et laisse la rotation au système.

Modifié

  • deploy/README.md : la checklist supposait un shell root sans jamais dire
    comment en obtenir un, alors qu'aucun hébergeur ne donne root — la première
    commande échouait après avoir eu l'air de fonctionner. Le piège du tube est
    signalé avec (sudo doit élever gpg et tee, pas curl).
  • La consigne de durcissement SSH nommait le fichier
    sshd_config.d/99-hardening.conf. sshd applique la première définition
    qu'il lit et parcourt les extraits dans l'ordre lexical — l'inverse de la
    convention systemd. Les images cloud Ubuntu livrent un 50-cloud-init.conf
    avec PasswordAuthentication yes, qui gagnait : le fichier de durcissement
    existait, disait la bonne chose, et ne faisait rien. Renommé en 01-, et la
    vérification lit désormais sshd -T plutôt que le fichier.
  • README.md : la construction de l'app de bureau réclame npm run build
    d'abord. electron-builder empaquette dist/ tel quel sans jamais le
    reconstruire, et dist/ est gitignoré, donc changer de branche puis
    empaqueter livrait la nouvelle coquille Electron autour de l'ancien jeu.
  • Le crédit d'imagerie Google descend au bas de la colonne FIELD, avec les
    autres mentions légales — licence, sources — au lieu d'être coincé entre le
    rail LIVE et ce qui décolle, où il se lisait comme une étape du parcours.
    Toujours sur LIVE seulement : le terrain déjà sur le disque a emporté son
    crédit avec lui.

Ajouté

  • Un pourboire, en trois marques. Le pied de page de FIELD porte les logos
    Cake Wallet, Bitcoin et Monero, dessinés dans la grille 12×12 du jeu, sous une
    ligne qui dit à quoi ça sert. Chacun ouvre une petite fenêtre par-dessus FIELD
    — la carte, l'épingle et la zone choisie restent exactement où elles étaient.
    Un logo se reconnaît avant de se lire, ce qu'un bouton « SUPPORT » ne faisait
    pas, et un pot à pourboires n'a pas besoin de tout le cadre pour dire une seule
    chose.

    Trois adresses — Monero, Bitcoin en paiement silencieux (BIP352), Bitcoin
    classique, les deux dernières dans la même fenêtre puisque c'est une seule
    décision pour qui donne — plus une poignée Cake lisible, fpvtp@cake.cash,
    la seule ligne qu'un humain peut retenir ou dicter : quatre-vingt-quinze
    caractères de base58 ne sont pas une interface. Chaque adresse est affichée
    en entier, jamais tronquée, et copiable d'un bouton qui dit s'il a réussi.

    Crypto uniquement : tous les rails fiat vérifient l'identité du bénéficiaire,
    ce que ce projet ne propose pas, et une page de paiement à l'état civil
    déferait le pseudonyme que le dépôt tient partout ailleurs. La fenêtre ne le
    dit pas — expliquer l'absence de bouton carte transforme une petite offre en
    plaidoirie ; c'est le README qui porte le raisonnement.

    Les adresses vivent dans un module pur, tools/support-model.mjs, pour une
    raison précise : tools/support-selftest.mjs les revérifie par checksum à
    chaque passage de CI
    — bech32 et bech32m pour Bitcoin, Keccak-256 pour
    Monero, l'implémentation étant elle-même contrôlée sur le vecteur de test
    officiel avant qu'on lui fasse confiance. Une coquille dans une légende est
    embarrassante ; une coquille dans une adresse envoie l'argent d'un inconnu là
    où personne ne pourra jamais le dépenser, et le dépôt comme les binaires la
    porteraient pour la durée de la version.

  • Le jeu dit où sont ses sources. Sous le pied de page de FIELD, une
    catégorie à part — « SOURCE · LEAVE A STAR ON GITHUB », le logo GitHub et
    AGPL-3.0 —, cliquable, et la même marque discrète dans l'OSD en vol.
    Ce n'est pas de la promotion : l'article 13 de l'AGPL exige qu'un joueur qui
    interagit avec le programme à travers un réseau se voie offrir les sources
    correspondantes — or sur l'instance de quelqu'un d'autre, il ne voit jamais le
    dépôt, ni le fichier LICENSE, ni le README. L'offre doit être dans le
    programme.

    Les icônes viennent du jeu lui-même : src/pixel-icons.js (PHASE 20, Bible
    §41) existait depuis longtemps et n'était branché à rien ; c'est son premier
    usage. La bibliothèque gagne quatre marques — GitHub, Bitcoin, Monero, un
    gâteau pour Cake Wallet — dessinées pour survivre à douze pixels : la
    silhouette pour GitHub, le ₿ sans sa pièce, l'anneau et le M de Monero. Le
    mot est ce qu'on décode, la marque est ce qu'on reconnaît. En vol elle n'est
    pas
    cliquable : le vol capture le pointeur, une cible dans l'image serait un
    piège ; c'est le pied de page du terminal qui porte le lien.

  • deploy/README.md gagne une section « Hardening the machine » : SSH par
    clés, restriction du port 22, fail2ban, mises à jour automatiques, et le
    mode SSL à vérifier derrière un CDN. Le service était déjà bien confiné par
    son unité systemd ; la machine, elle, n'était couverte nulle part.


Which file do I download?

File For whom
FPVTP-*-win-x64.exe Play on Windows. Installer: Start Menu entry, uninstaller, automatic updates. It is not code-signed, so SmartScreen warns on first launch.
FPVTP-*-linux-x86_64.AppImage Play on Linux. Make it executable, double-click. Automatic updates.
fpvtp-server-*-linux-x64.tar.gz Host an instance. The server, the built game, a Node runtime and deploy/ (systemd unit, Caddyfile, delivery script, checklist). No npm install to run.
latest.yml, latest-linux.yml, *.blockmap Update plumbing, read by the installed app. Not meant to be downloaded by hand.

There is no macOS build.

To play: take the one file for your system, that is the whole install.

To host: unpack, then follow deploy/README.md. The server listens on
127.0.0.1 and refuses to listen wider without --mode shared, which
then demands an operator key on every API request.

The game is under AGPL-3.0: if you host a modified version
for other people, you must publish its sources to them.

v1.0.0

Choose a tag to compare

@github-actions github-actions released this 13 Sep 12:59
72c4226

Première version publique. Le jeu existait déjà en 0.3.0 ; ce qui change ici,
c'est qu'il est fait pour être rencontré par quelqu'un d'autre que son auteur.

  • On vole au-dessus d'une vraie ville, dans le navigateur, en photogrammétrie
    Google Earth diffusée pendant le vol. Aucun terrain à télécharger d'abord :
    on clique un point sur la carte, on vole quinze secondes plus tard, et les
    tuiles vont directement de Google au navigateur du joueur sans passer par un
    serveur.
  • Le clavier est jouable. Sans manette, le vol démarre en angle et les axes
    montent progressivement ; une manette reçoit toujours de l'acro inchangé.
  • Un navigateur sans WebGL2, un serveur de tuiles bloqué, un délai dépassé :
    les trois disent maintenant ce qui se passe au lieu d'une page noire, d'une
    impasse ou d'un vide infini.
  • Une passe de sécurité complète, avec exploits reproduits : évasion par lien
    symbolique, injection HTML stockée, limite d'inscription contournable,
    routes non bornées, allocation pilotée par le réseau, et deux portes
    Electron.
  • L'imagerie Google est créditée sur le chemin que tout le monde emprunte.
    Elle ne l'était pas.
  • Les surfaces publiques — README, workflows, notes de version, manuel,
    serveur, outils — sont en anglais.
  • 2 700 vérifications automatiques et une passe de fuzzing à graine fixe dans
    la même chaîne, exécutée avant chaque publication.

Le détail, rubrique par rubrique.

Ajouté

  • Un navigateur sans WebGL2 dit pourquoi, au lieu d'une page noire sans un
    mot. three r170 demande un contexte webgl2 et rien d'autre, et
    WebGLRenderer lève au niveau module : main.js était interrompu avant même
    que le Hud qui aurait pu le signaler existe. La sonde vit maintenant dans
    index.html, en script classique, avant le module — sans bundle, sans
    feuille de style, sans police, styles en ligne : quoi qu'il ait échoué plus
    bas, ces mots arrivent à l'écran. Elle nomme les quatre choses qui règlent
    vraiment le problème.

  • L'écran d'échec a une sortie : [ RELOAD ], Échap et Entrée. Il n'en avait
    aucune, ce qui faisait de tout blocage de kh.google.com — un bloqueur de
    publicité, un VPN, un proxy d'entreprise — la fin de la visite. Le message
    nomme désormais cette cause au lieu de se taire.

  • Les fichiers qu'un dépôt public doit avoir : CONTRIBUTING.md,
    SECURITY.md, CODE_OF_CONDUCT.md, un gabarit de pull request, une
    configuration de gabarits d'issue qui ferme l'issue vide et route les
    questions vers Discussions et les vulnérabilités vers le formulaire privé,
    et dependabot.yml.

  • Nouveaux selftests : first-run-selftest.mjs (18 vérifications, dont
    l'exécution de la vraie sonde d'index.html), rocktree-unpack-selftest.mjs
    et le modèle pur boot-failure-model.mjs.

  • Une passe de fuzzing, npm run fuzz (sim/tools/fuzz.mjs pour les
    modules purs, sim/tools/fuzz-api.mjs pour les routes HTTP contre un vrai
    serveur, harnais partagé dans sim/tools/lib/fuzz.mjs). Seize cibles, chacune
    avec l'invariant qu'elle vérifie et le modèle de menace de son entrée ; graine
    fixe, donc rejouable et intégrée à selftest:ci. Ce qu'elle a trouvé est dans
    sim/docs/handoff-archive/fuzzing.md.

  • Bibliothèque musicale : 143 pistes au lieu de 73. Chaque pool double à peu
    près, et le drone d'essaim reçoit enfin le sien, swarmNode, 10 pistes. Aucune
    piste retirée.

  • Dialogue : un nouveau lot d'environ 100 répliques par shard sur les onze
    événements, soit 1 100 entrées de plus.

  • JUKEBOX (#120), cinquième voie à la racine : la bibliothèque musicale entière,
    enfin écoutable. Jusqu'ici un morceau ne s'entendait que si le tirage le
    donnait — déterministe sur la famille et la graine du drone — et tout le reste
    restait invisible. C'est une radio et pas un lecteur : elle enchaîne toute
    seule, et elle continue de jouer quand on la quitte, dans les menus comme
    en vol. On choisit sa bande-son, puis on décolle avec.

    Elle n'est pas la musique du vol pour autant. L'arc du hack — la musique
    sourde, le duck du rituel, l'explosion au drop, l'intensité qui suit le
    pilote, la mort au choc — appartient à FIELD et ne bouge pas d'un pouce
    lorsque la radio est éteinte. Quand elle joue, elle joue à plat et le vol ne
    la touche plus : ni filtre aux gaz, ni coupure au crash.

  • Un pool musical pour SWARM NODE (#116). La 7ᵉ famille — le nœud de
    commandement d'un essaim — était absente de MUSIC_POOLS : le vol le plus
    rare du jeu était aussi le seul à se jouer en silence. Son noyau est une
    techno dure menée par le kick, hoover gras en lead, sèche et proche ; à
    Carpenter elle emprunte l'ossature — ostinato mineur figé sur une pédale de
    basse immobile — et non le timbre. 132-142 BPM.

  • Mode turtle (#105). Une machine sur le dos n'avait qu'une issue depuis D9 :
    couper le lien et la perdre. Une touche — T par défaut, remappable comme les
    autres — la remet à l'endroit, et la ligne [T] TURTLE s'affiche à l'écran
    dès que la machine est immobile ET sur le dos, au-dessus du rappel
    [HOLD K] CUT LINK : des deux issues, celle qui rend la machine se lit avant
    celle qui la perd. Le retournement est assisté plutôt que piloté aux moteurs
    inversés (pas de motors[4] signé, pas de modèle de pale inversée), mais son
    couple est plafonné à ce que deux moteurs de l'appareil peuvent réellement
    produire, et il s'arrête seul — assiette rétablie, ou délai dépassé.

  • La culmination du hack est de retour (#101). Le retrait du CONTROL VECTOR
    (#33) avait supprimé src/ritual.js en entier, alors que le problème tenait
    à la moitié haute du fichier : la saisie d'un vecteur mémorisé hors du jeu,
    qui bloquait un joueur l'ayant oublié. La culmination qui suivait est partie
    avec elle, et [ JACK IN ] coupait droit au résultat.
    Elle revient seule, sur son propre écran entre l'invite et CONTROL ACQUIRED : src/culmination.js, une à quatre secondes plein écran
    (variante V1–V4 tirée sur la graine de la cible,
    tools/culmination-model.mjs), les primitives demo scene pondérées par
    famille (FAMILY_PRIMITIVES, revenu dans src/hack-grammars.js), les quatre
    couleurs d'événement, un coup à chaque battement, et la signature sonore de
    la famille (CULMINATION_SCORES / scoreFor dans
    tools/ui-audio-model.mjs, uiAudio.playCulmination()) pendant que la
    musique se retire. Rien à presser : elle démarre seule, rend la main seule,
    Échap saute le battement. prefers-reduced-motion la réduit à un seul
    battement sans flash.
    Ce qui ne revient pas : la saisie du vecteur, son riser (ritualTension) et
    le blocage qu'ils portaient. La Bible §19 compte donc à nouveau deux porteurs
    de la palette demo scene, l'intro et la culmination, ce que vérifient
    tools/palette-selftest.mjs et tools/intro-primitives-selftest.mjs.

  • Le modèle de vol connaît maintenant le vol en translation (#91). Trois
    mécanismes qui manquaient, et que tout pilote ressent :

    • Portance de translation : en avançant, le rotor s'échappe de son propre
      flux induit et gagne en rendement — +21 % de poussée à 20 m/s sur le 5"
      de référence. Ce n'est pas un terme de plus : kInflow EST déjà la pente
      d'inflow de la théorie du disque, et le nouveau calcul la GÉNÉRALISE, en
      forme fermée (Glauert), sans itération à 250 Hz. L'air calme et le vol
      purement vertical restent identiques au bit près, et la branche de descente
      est laissée telle quelle : entre −2·vh et 0 la théorie n'a pas de solution
      du tout, et ce régime est déjà modélisé empiriquement comme propwash.
    • Flapback : ajouté puis retiré avant publication (#103, voir
      Corrigé plus haut) — les deux moments qu'il apportait rendaient l'appareil
      impilotable en vitesse.
    • Précession des rotors : un lacet pendant un roulis déplace le nez.
      Complémentaire du terme d'inertie d'hélice déjà présent en lacet, pas
      redondant : l'un a besoin que le régime CHANGE, l'autre seulement qu'il ne
      soit pas nul.
      Aucun nouveau réglage par famille : tout se dérive de la géométrie et des
      coefficients existants.
  • sim/tools/aero-selftest.mjs : banc sans Rapier, sans scène et sans
    navigateur, dans la chaîne CI, qui affirme des identités et jamais des
    nombres relevés — le résidu de Glauert, la limite de saturation contre la
    constante d'inflow elle-même, le câblage exact de la précession avec l'inflow
    coupé pour l'isoler. Il porte aussi une version headless de la porte
    anti-divergence sous roulis tenu, qui exigeait Rapier et une scène installée.

  • node tools/tune-pid.mjs --cruise fait voler le banc en avant, à la vitesse
    d'équilibre propre à chaque famille, et juge un candidat sur le PIRE des deux
    régimes. Les PID livrés ne changent pas : au point de fonctionnement du banc
    le plant n'a pas bougé — npm run tune est identique au bit près — donc le
    tune reste exactement aussi mesuré qu'avant.

  • La marque entre dans le jeu (#73). docs/brand.md réservait depuis toujours
    le verrouillage empilé — le symbole, puis F P V T P ! dessous — au « splash,
    boot » ; il n'avait jamais été posé, et la marque ne sortait que du favicon et
    de la carte Open Graph. Elle tient maintenant le cracktro de lancement, et
    elle s'y trace module par module : le cadre d'abord, parce que le cadre
    EST le panneau, puis les quatorze cellules en ordre de lecture, puis le nom
    s'inscrit dessous. La marque est un randomart figé (brand.md) et un
    randomart, dans ce jeu, ça se trace (#57).

  • Tout tient dans la phase reveal de l'intro : aucune durée nouvelle,
    tools/intro-model.mjs ne bouge pas, et le selftest refuse un tracé qui
    déborderait sur la plasma. Le sinus-scroll ne possède plus que la phase
    plasma — pendant reveal et à la résolution le verrouillage est immobile et
    exact, c'est-à-dire juste aux deux moments où l'œil le lit.

  • La marque ne prend jamais une couleur demo, pas même sous la plasma : le
    cyan et le magen...

Read more

v0.3.0

Choose a tag to compare

@github-actions github-actions released this 08 Sep 17:23

Ajouté

  • Le menu a quatre voies au lieu de deux : FIELD, BENCH, ARCHIVE,
    SETTINGS, à la racine et dans cet ordre. ARCHIVE n'est plus un lien enterré
    dans un onglet de FIELD, SETTINGS n'est plus répété à trois endroits, et
    fpvtp.mode retient les quatre (#6, #7).
  • Un briefing de quatre écrans (INPUT, THE TERMINAL, A SESSION,
    BRIEFING COMPLETE) accueille un opérateur qui vient d'être créé, juste
    après le CONTROL VECTOR. Il énonce, il n'ordonne pas ; Échap le saute ;
    [ CALIBRATE ] et [ MAP KEYS ] ouvrent le bon onglet de SETTINGS et
    reviennent, et l'écran INPUT lit le mappage en direct. Il se rejoue par
    SETTINGS › SYSTEM › [ REPLAY BRIEFING ]. Le premier vol hors banc
    affiche trois lignes brèves — THROTTLE UP, [TAB] SETTINGS,
    [HOLD K] CUT LINK, cette dernière nommant la touche réellement liée et
    comptée depuis le décollage — puis plus jamais (#16).
  • Le panneau SETTINGS (Tab) passe à la direction artistique du terminal :
    en-tête FPVTP! // SETTINGS, quatre onglets CONTROLLER · KEYBOARD · AUDIO · SYSTEM, un corps à la fois, et l'onglet ouvert est retenu pour la session.
    KEYBOARD liste chaque action avec ses touches et un [ REBIND ] : la
    touche suivante est prise, Échap annule, une touche déjà prise déclenche un
    échange annoncé sur la ligne, [ RESET KEYS ] remet les valeurs d'usine.
    SYSTEM porte la portée d'affichage (mode ?live=), [ RESET SETTINGS ]
    et le numéro de version (#15).
  • Les commandes clavier passent par une table remappable (src/key-map.js) :
    une action porte un nom (throttleUp, pause, cutLink…), ses touches se
    changent, et les valeurs par défaut couvrent QWERTY et AZERTY (W/Z, A/Q).
    Réglages rangés dans fpvtp.keyMap ; Tab, Échap et Entrée restent fixes.
  • La caméra libre (C, une orbite qui gelait le monde) devient une bascule de
    vue V : FPV / CHASE. La vue CHASE est la caméra de vol reposée 1,1 m
    derrière le nez et 0,45 m au-dessus, champ plafonné à 75° et OSD de la cible
    débranché (c'est une caméra extérieure, pas le flux vidéo), la simulation
    continue de tourner derrière elle, et elle marche sur tous les chemins
    (LOCAL, LIVE, BANC). Un
    bouton [V] FPV / [V] CHASE en haut à droite de l'OSD fait le même geste
    à la souris. Chaque vol commence en FPV (#12).
  • L'écran de fin de vol montre la machine perdue en 3D, celle qui volait —
    livrée, numéro et châssis compris — et on peut la tourner à la souris. Elle
    tourne seule d'un tour toutes les 24 s. Sans contexte WebGL, le portrait fil
    de fer d'avant prend le relais ; l'archive, elle, garde le SVG (#13).
  • Tests couvrant qu'un vol EN DIRECT remplit bien le Session Log, le Target
    Log et le compteur OPERATOR, et n'est jamais proposé en REVISIT/RESUME (#8).

Modifié

  • FIELD ouvre sur l'onglet LIVE, désormais placé avant LOCAL : c'est la voie
    qui marche sans rien avoir téléchargé. Sur un serveur qui n'acquiert pas,
    l'onglet LOCAL est éteint et dit en trois lignes pourquoi, au lieu de laisser
    une liste vide (#6).

  • La tête de FIELD ne salue plus l'opérateur (la racine le fait, une fois) et
    son pied ne compte plus rien : il dit LOCAL INSTALLATION · BUILD n ou
    SHARED SERVER · BUILD n. Les compteurs vivent dans ARCHIVE › OPERATOR (#6).

  • Échap est écrit sur les écrans qui l'écoutent : [ESC] OPERATION MODE sous
    FIELD, BENCH et ARCHIVE, [ESC] BACK sur les écrans en dessous (#7).

  • Le panneau SETTINGS prend le noir du terminal, ses filets et ses trois
    niveaux typographiques, et remplace son bouton Close (Tab) par la ligne de
    touches [ESC] CLOSE · [TAB] CLOSE. Le rappel clavier figé qui vivait sous
    Controls a disparu : l'onglet KEYBOARD le remplace, et il dit la vérité.

  • L'écran affiche la vraie version du paquet (v0.0.0, ou dev hors build
    Vite) au lieu de la constante de lore 0.97b (#9).

  • Le chargement des cartes LIVE ne refait plus la marche rocktree à chaque
    recalcul
    (#21). kh.google.com interdit au cache HTTP de garder ses
    réponses : tous les 50 m de vol, la fenêtre de streaming redemandait les
    344 bulks d'une fenêtre de 300 m depuis la racine. La traversée est
    désormais pipelinée (16 bulks en vol, plus de lots séquentiels de 8) et
    garde ses bulks dans le worker pour toute la session ; la fenêtre ne
    désire que les nœuds dont la boîte recoupe le disque de chargement (15,7 %
    de nœuds en moins, tous dans le brouillard de bord) ; bootLive() lance
    la première traversée avant d'attendre Rapier et crée ses workers
    d'emblée. Mesuré, service réel, 60 ms de latence émulée par requête :
    traversée de boot 4,3 s → 2,0 s, recalcul en vol 3,5 s → 80 ms.

  • Build de production découpé et précompressé (#21). Rapier (2 Mo de
    WASM en base64) est chargé par import() dans src/physics.js — chunk
    séparé, préchauffé pendant le terminal, le menu ne l'attend plus ; three
    a son propre chunk, en cache d'une version à l'autre. npm run build
    enchaîne tools/precompress.mjs (.br/.gz à côté des fichiers texte,
    4,8 Mo → 1,0 Mo) et server/static.mjs les sert avec Content-Encoding,
    Vary, une ETag par représentation, jamais sur un Range, jamais si la
    variante est plus vieille que sa source. Onze vérifications de plus dans
    server-selftest.mjs.

  • Niveau de détail par anneaux en LIVE (#22) : niveau 21 jusqu'à 150 m
    du drone, 20 jusqu'à 300 m, 19 au-delà (tools/lib/rocktree/lod.mjs). Une
    traversée par anneau (les suivantes servies par le cache de bulks), puis un
    assemblage qui fait exclure aux nœuds grossiers les octants qu'un nœud plus
    fin dessine — chaque point du disque couvert exactement une fois, vérifié
    sur un octree synthétique jusqu'aux coutures. Mesuré, service réel : 1259 →
    740 nœuds à 300 m, 4176 → 1003 à 600 m.

  • Cache disque des réponses rocktree (#22, src/rocktree-cache.js,
    Cache API) : NodeData et BulkMetadata persistent entre sessions dans les
    Workers — REDEPLOY et un second vol au même endroit ne repassent plus par
    le réseau. Jamais PlanetoidMetadata (l'epoch), jamais une réponse non-ok,
    5000 entrées au plus, fetch nu sans Cache API.

Corrigé

  • Une installation locale ne se présente plus comme un serveur partagé. Le pied
    de FIELD et l'avis de l'onglet LOCAL se lisaient sur le droit d'acquérir,
    fermé par défaut sur toute build distribuée : le client de bureau affichait
    donc « SHARED SERVER » et se conseillait à lui-même d'installer le client de
    bureau. GET /__map-api/scenes rend désormais le mode du serveur
    (local | shared), et c'est lui qui décide de ces deux formulations ;
    DRAW BOX / DRAW SHAPE continuent de se lire sur le droit d'acquérir.
  • Le portrait de la machine manquait sur deux fins de vol sur trois — sortie de
    zone et lien coupé — et sur tout vol NOMINAL (?family=, ?scene=, ?live=,
    NOMINAL au banc), faute d'exemplaire tiré. Chaque fin porte désormais son
    portrait, et une famille sans tirage en a un déduit de son nom (#13).
  • Face au soleil, l'exposition ferme moins fort : entre 55 et 75 % de son
    niveau au repos au lieu de tomber à 35 %, l'image reste pilotable (#11).

Retiré

  • Le lien MODE du pied de FIELD (Échap faisait déjà exactement la même chose),
    les liens SETTINGS du pied de FIELD, de la rangée ARCHIVE et du pied du
    banc, l'entrée ARCHIVE de la rangée LOCAL, la ligne DESKTOP CLIENT AVAILABLE et la mention STREAMED NOW · NOTHING KEPT · NEEDS THE LINK de
    l'onglet LIVE, qui était fausse : un vol en direct est archivé comme les
    autres (#6, #7).
  • L'atterrissage. Un vol se termine par un crash, une sortie de zone ou le
    pilote qui coupe le lien (K maintenue) : plus de désarmement (touche J, geste
    manette), plus de verdict LANDED, plus d'écran POST-FLIGHT ANALYSIS ni de
    reprise de session. Les vieux journaux qui portent LANDED se relisent et
    s'affichent tels quels (#10).

Quel fichier télécharger

Fichier Pour qui
FPVTP-*-win-x64.exe Jouer sous Windows. Installeur : entrée Menu Démarrer, désinstalleur, mise à jour automatique.
FPVTP-*-linux-x86_64.AppImage Jouer sous Linux. Rendre exécutable, double-cliquer.
fpvtp-server-*-linux-x64.tar.gz Héberger une instance. Le serveur, le jeu construit, un runtime Node, et deploy/ (unité systemd, Caddyfile, script de livraison, checklist). Aucun npm install à faire.
latest.yml / latest-linux.yml Les flux de mise à jour automatique. Ne pas télécharger à la main.

Héberger : décompresser, puis suivre deploy/README.md. Le serveur
écoute sur 127.0.0.1 et refuse d'aller plus loin sans --mode shared,
qui réclame alors une clé d'opérateur à chaque requête.

Le jeu est sous AGPL-3.0 : si vous en hébergez une version
modifiée pour d'autres personnes, vous devez leur en publier les sources.

v0.1.0-beta

Choose a tag to compare

@github-actions github-actions released this 07 Sep 23:18

Ajouté

  • sim/server/ — le jeu démarre sans Vite (#259, tranche T1 du design de
    déploiement). node server/index.mjs [--data <dir>] [--port 8080] [--host 127.0.0.1] [--mode local|shared] [--dist <dir>] [--open], avec les
    variables d'environnement FPVTP_DATA_DIR/FPVTP_PORT/FPVTP_HOST/
    FPVTP_MODE. api.mjs porte /__operator et /__map-api — les deux tables
    de routes déplacées telles quelles, aucun chemin, aucune méthode, aucun code
    de statut ni aucune forme de réponse ne changent ; static.mjs sert le
    dist/ de Vite, avec Range (reprendre le téléchargement d'un chunk de
    scène), ETag faible, Cache-Control: immutable sur /scenes/<slug>/*, et
    aucun repli SPA : un fichier absent rend un 404 JSON, jamais index.html
    (le pendant serveur de #275). Aucune dépendance npm : du node:http nu.
  • sim/tools/lib/paths.mjs — un seul module résout le répertoire de données
    (scenes/, scenes.json, operator-state/, cache/google-earth/). Sans
    FPVTP_DATA_DIR, il rend exactement les chemins d'aujourd'hui : npm run dev
    ne bouge pas d'un octet, et FPV_OPERATOR_DIR reste honoré.
  • sim/tools/server-selftest.mjs (26 vérifications) et
    sim/tools/vite-adapter-selftest.mjs, chaînés dans selftest:ci.
  • LICENSE (GNU AGPL-3.0-only) et un README.md à la racine : le dépôt se
    prépare à devenir public. docs/manuel.md reste le README technique.
  • .githooks/pre-commit — refuse un commit signé par une adresse hors liste
    blanche. git config core.hooksPath .githooks l'active dans un clone.
  • Le jeu s'installe comme un jeu (#291, tranche T2) : un installeur .exe
    sous Windows — entrée Menu Démarrer, désinstalleur — et une AppImage sous
    Linux. L'app est un seul process Electron qui démarre le serveur du jeu sur
    la boucle locale, sur un port éphémère, et ouvre une fenêtre dessus : ni
    terminal, ni navigateur à part. Les données (scènes, sessions, état
    opérateur) vivent hors du dossier du programme — app.getPath('userData'),
    forcé sur %LOCALAPPDATA% plutôt que le %APPDATA% itinérant par défaut —
    donc une mise à jour n'écrase rien. electron-updater est câblé sur un flux
    HTTP générique (le dépôt est privé : GitHub Releases demanderait un jeton à
    chaque téléchargement) dont l'adresse reste un point d'ancrage explicite tant
    que le serveur n'existe pas. Pas de macOS, pas de signature de code :
    décisions actées.
  • Une clé d'opérateur pour les serveurs partagés (#60, tranche T3). Créer
    un opérateur produit un secret de 128 bits — base32 sans caractères ambigus,
    groupé par 4 — stocké haché en SHA-256 et rendu une seule fois. Un serveur en
    --mode shared le réclame en Authorization: Bearer sur /__operator/:id/*
    et /__map-api/* (401 sans, 403 avec une mauvaise) et ne publie plus
    d'annuaire (404 sur la liste). L'inscription reste en libre service —
    c'est le cas nominal sur un serveur partagé — mais plafonnée par adresse, et
    les captures d'un opérateur ont un plafond cumulé. GET /__operator/whoami
    retrouve un profil par sa clé depuis un autre navigateur, et
    node server/index.mjs key <id> en délivre une neuve : c'est la migration
    des fichiers existants et la seule voie de récupération. Un serveur local
    ne lit jamais l'en-tête
    : sa frontière reste le socket, npm run dev ne
    change pas.
  • Côté joueur, la clé se tait : le navigateur la garde, l'inscription ne
    fait rien noter à personne, et [ SHOW KEY ] dans ARCHIVE > OPERATOR la rend
    le jour où l'on veut emporter son profil ailleurs — sur le modèle de
    [ SHOW VECTOR ], sans jamais se confondre avec le Control Vector. Un
    serveur qui ne reconnaît pas le navigateur ouvre un écran où
    [ NEW OPERATOR ] est l'action principale et la saisie d'une clé la porte de
    secours.
  • deploy/ (#292, tranche T4) : l'unité systemd du serveur en mode partagé
    (écoute sur la boucle locale seulement, données hors du dossier du programme,
    acquisition délibérément fermée, ProtectSystem=strict), la configuration
    Caddy de ses deux entrées publiques — le jeu derrière TLS, et un sous-domaine
    statique et sans authentification qui distribue les installeurs et leurs
    fichiers de mise à jour — un script de livraison qui télécharge une release
    privée, bascule un lien symbolique, redémarre et vérifie que le service
    répond avant de rendre la main, en laissant la version précédente intacte
    pour un retour arrière en deux commandes, et la checklist qu'un humain suit
    une fois pour préparer une machine neuve. Rien n'est déployé : la première
    livraison reste manuelle.

Modifié

  • Dépendances remontées (PR #5, groupe npm_and_yarn) : sharp 0.33 → 0.35,
    Vite 5 → 6, electron-builder 25 → 26, et Electron 33 → 44 — pas 39 comme
    proposé initialement : 39 est hors de la fenêtre de support d'Electron (les
    trois derniers majeurs) et laissait ouverte l'alerte de traversée de chemin
    d'extract-zip. npm audit ne rapporte plus rien. Aucune des ruptures d'API
    de sharp 0.35 (failOnError, paletteBitDepth, jp2k) n'était utilisée.
  • sim/electron/main.js suit la nouvelle signature du relais
    console-message : Electron ≥ 36 passe un seul objet d'événement et un
    level textuel, pas quatre arguments avec un niveau numérique. L'ancienne
    forme ne journalisait plus rien.
  • sim/tools/map-api-plugin.mjs n'est plus qu'un adaptateur Vite de vingt
    lignes : il monte createApi() sur les middlewares du serveur de dev, avec
    son logger. Toute la logique a migré dans sim/server/api.mjs.
  • sim/tools/session-api-selftest.mjs teste désormais le serveur autonome
    plutôt que Vite — il teste ce qui est livré, et il passe de 208 ms à 85 ms.
  • L'acquisition de terrain est fermée par défaut (#60) : elle n'est active
    que si FPVTP_ACQUIRE vaut 1 ou true, et jamais en --mode shared,
    quoi qu'il arrive — deux gardes indépendantes. Fermée, elle retire
    [ DRAW BOX ] et [ DRAW SHAPE ] de l'écran et laisse l'onglet LIVE, qui
    porte déjà la boucle complète ; une ligne au pied signale alors le client de
    bureau, sans rien promettre de plus que jouer chez soi. Conséquence pour le
    développement : npm run dev veut désormais FPVTP_ACQUIRE=1 dans
    l'environnement pour retrouver ACQUIRE AREA.
  • La CI vérifie le dépôt sous Windows autant que sous Linux (#291) : la
    matrice {ubuntu, windows} de ci.yml a déjà fait tomber une comparaison de
    chemin (provider-selftest.mjs) et deux dépendances à la locale du système.
    Un .gitattributes racine impose eol=lf : une soixantaine de selftests
    découpent sur \n, et core.autocrlf est vrai par défaut sur les runners
    Windows.
  • sim/public/scenes.json est committé vide : c'est un fichier généré, propre
    à chaque installation, et il portait trois entrées fantômes qui faisaient
    échouer npm run selftest:scenes et affichaient trois scènes inexistantes sur
    un clone neuf. node tools/sync-scenes.mjs --adopt le reconstruit depuis le
    disque.
  • tools/imagery-selftest.mjs (16 vérifications) est enfin chaîné dans
    selftest:operator : il existait sans jamais tourner.
  • La release publie de quoi démarrer un serveur : release.yml attache
    désormais un fpvtp-server-<tag>-linux-x64.tar.gz (app/ avec server/,
    tools/, src/, dist/, plus le runtime Node de la version qui vient de
    passer les selftests) à côté de l'archive dist seule. C'est ce que
    deploy/deploy.sh installe. Aucun npm install sur le VPS : le serveur
    démarre sans node_modules, mesuré.

Modifié

  • Le nom fpvmaps disparaît du dépôt, jusqu'au préfixe des clés
    localStorage (fpvmaps. → fpvtp.), au nom du paquet npm (fpvtp-sim),
    à celui du plugin Vite (fpvtp-map-api) et à la métadonnée generator des
    .glb exportés. Aucune migration : un joueur qui met à jour repart avec
    des réglages neufs — calibrage manette, volumes, réglages d'objectif. Son
    opérateur, lui, n'est pas perdu : il vit côté serveur, et OPERATOR SELECT
    le repropose.
  • Le README de la racine est réécrit autour de ce qu'un nouveau venu vit
    vraiment : une capture d'écran, ce qu'on peut faire tout de suite sur un
    clone neuf (voler en LIVE, puisqu'il n'y a aucun terrain sur disque), les
    contrôles, et les trois façons de faire tourner le jeu.
  • Le dépôt est désormais lionrayonnant/FPVThePlanet : toutes les références
    internes, deploy/deploy.sh et l'unité systemd comprises, pointent dessus.

Modifié

  • La release publie ce qu'il faut pour héberger sa propre instance.
    L'archive fpvtp-server-<tag>-linux-x64.tar.gz emporte désormais deploy/
    (unité systemd, Caddyfile, script de livraison, checklist) et la LICENSE —
    que l'AGPL exige de faire accompagner le programme distribué — en plus du
    serveur, du jeu construit et d'un runtime Node. Toujours aucun npm install
    à faire sur la machine d'accueil. La licence voyage aussi dans l'application
    Electron (extraResources).
  • Le corps de la GitHub Release liste maintenant les fichiers et dit lequel
    télécharger selon qu'on veut jouer ou héberger.
  • Le workflow refuse de publier une archive qui ne démarre pas : le runtime
    embarqué doit résoudre server/index.mjs avant que l'archive soit scellée.
  • L'archive fpvtp-sim-<tag>.zip (le dist/ seul) disparaît : elle ne pouvait
    pas démarrer — c'est précisément ce que #259 reprochait aux « livraisons »
    d'avant.

Modifié

  • Un seul README, à la racine. Le dépôt en avait deux, et rien ne disait
    lequel lire : sim/README.md devient docs/manuel.md — il reste entier,
    mais ce n'est plus un README. La racine est la porte d'entrée, le manuel est
    le manuel. Les références de la documentation vivante suivent ; les plans et
    specs d'archive gardent les leurs, ils racontent ce qui a été édité ce
    jour-là.

Corrigé

  • Le scanner disait NO LOCAL TERRAIN — DRAW AN AREA ON THE MAP alors que
    [ DRAW BOX ] et [ DRAW SHAPE ] s...
Read more