Repository navigation
FR Creer Fin Scellee
English · Type : procédure · Public : auteur · Contexte : dépôt du moteur, projet créé · Statut : prête · S'applique depuis : 4.1.2
La fin scellée est un module facultatif : les derniers textes de votre jeu (un ticket à gratter, une annonce, une carte finale avec photos) sont chiffrés dans un seul fichier avec un mot de passe, et ne sont donc jamais dans le code du jeu. Un joueur qui ouvre les fichiers du jeu construit n'y lit rien ; la fin ne se montre que quand le jeu l'atteint. Cette page la met en place, scelle une issue et vérifie que rien n'a fuité.
Un fichier public/data/dossier.bin qui contient une issue choisie, chiffrée ; un jeu dont le module ending joue le
ticket à gratter, les confettis et le jingle, puis la carte finale ; et un build dans lequel npm run check:spoilers ne
trouve aucun texte de fin en clair.
- Le dépôt du moteur :
npm run sealetnpm run check:spoilerssont des scripts du dépôt du moteur, pour le jeu sélectionné (GAME=<id>ounpm run game). - Le champ
endinget sa lecture existent dans tout jeu. Depuis 4.1.2 (npm run sealn'affiche plus le mot de passe). Le type estEndingDefdepuis 4.0 ;RevealDefest son ancien nom, déprécié, retiré en 5.0.
Limite ·
engine-repo-onlyLa commandequest-n-clickd'un projet créé n'a nisealnicheck:spoilers. Son jeu peut jouer une fin scellée, mais le fichier se scelle depuis le dépôt du moteur.
- Le dépôt du moteur, installé (Installer depuis le dépôt).
- Un script qui termine le jeu avec la commande de fin (plus bas) et, si le joueur fait un pronostic, un drapeau que le script pose avec sa réponse.
Dans le dépôt du moteur, à sa racine, votre jeu sélectionné. La configuration privée vit dans games/<GAME>/private/,
que .gitignore tient hors du dépôt.
GameDef.ending le décrit :
// games/<GAME>/game.ts
ending: {
file: 'data/dossier.bin', // produit par npm run seal
password: { given: '…' }, // ou { typed: true, prompt: 'Mot de passe ?' }
guess: { flag: 'pronostic', labels: { a: '…', b: '…' }, right: '… {guess} …', wrong: '…', none: '…' }, // pronostic jugé sur la carte
scratch: { ticket: 'items/r4c1', sfx: 'grattage' }, // paramètres du mini-jeu scratch
card: { accent: '#d4145a' }, // couleur du cadre de la carte et du texte gratté
},| Champ | Sens |
|---|---|
file |
le fichier scellé, chargé sous le chemin de base du jeu. npm run seal écrit public/data/dossier.bin : écrivez donc data/dossier.bin
|
password |
{ typed: true, prompt } : le joueur le tape, il n'est nulle part dans le bundle. { given } : le moteur l'a, il est donc dans le bundle : une obfuscation, pas un secret |
guess |
facultatif : le pronostic du joueur, demandé au début (un drapeau que pose un script) et jugé sur la carte finale. labels donne le mot de chaque valeur du drapeau ; {guess} est remplacé dans right, wrong et none
|
scratch |
les paramètres du mini-jeu de grattage : ticket (l'image) obligatoire, sfx, color… ; le texte caché vient du fichier scellé |
card |
accent : la couleur du cadre et du texte gratté (#d4145a par défaut) |
La commande { ending: true, after: […] } joue, dans l'ordre : le ticket à gratter (le texte vient du fichier
chiffré), les confettis (skin.icons.confetti, skin.sounds.confetti) et le jingle (skin.sounds.jingle), puis
after, puis la carte finale (musique skin.sounds.end). Elle termine le jeu comme end (state.done, l'événement
endingReached, une sauvegarde). { reveal: true } est l'ancien nom. Juste avant, le scénario joue ce qu'il veut (la
famille autour du canapé, le cadenas qui fond…).
Les textes de la fin ne sont jamais dans le contenu du jeu : ils sont dans games/<GAME>/private/ending.config.ts.
Si le fichier ne peut être lu ou déchiffré, le jeu affiche « … » à la place de la fin.
-
Écrire la configuration privée à partir de l'exemple versionné, puis remplir les textes :
# dans le dépôt du moteur mkdir -p games/<GAME>/private && cp games/<GAME>/ending.config.example.ts games/<GAME>/private/ending.config.ts
Corrigez le chemin de l'import dans la copie : l'exemple importe
../../scripts/seal-types; depuisprivate/, c'est../../../scripts/seal-types. Sonpassworddoit être identique àending.passworddansgames/<GAME>/game.ts(ou à ce que tapera le joueur). L'exemple du jeu de démo estgames/demo/ending.config.example.ts.
-
Sceller une issue. Seule l'issue choisie est chiffrée :
# dans le dépôt du moteur npm run seal -- --outcome=<key>
<key>est l'une des clés deoutcomes. La commande affiche✔ Sealed file (<key>) → public/data/dossier.bin (<taille> KB); le mot de passe n'est jamais affiché.
-
Construire et chercher les fuites.
# dans le dépôt du moteur npm run build && npm run check:spoilers
npm run buildlance déjàcheck:spoilersà la fin (build:game) ; le relancer après un build ne coûte rien.
La configuration privée (EndingConfig, scripts/seal-types.ts) :
| Champ | Sens |
|---|---|
password |
identique au ending.password du jeu (given), ou à ce que tape le joueur (typed) |
outcomes |
des clés libres, chacune { ticket, headline, lines? } : le texte sous la zone à gratter (HTML simple), l'annonce de la carte, des lignes en plus. La clé scellée est comparée au drapeau du pronostic (ending.guess.flag) |
message |
un mot court, commun à toutes les issues |
photos |
les photos de la carte, chemins relatifs à games/<GAME>/private/ (jpg, png, webp, gif). seal avertit au-delà de 800 000 octets par photo |
lines |
des lignes communes, ajoutées après celles de l'issue |
judgeGuess |
false : le fichier scellé ne porte pas l'issue, et le pronostic n'est pas jugé (une version de test) |
npm run seal -- --outcome=<key> (scripts/seal.ts) lit
games/<GAME>/private/ending.config.ts ; sans lui, il prend l'exemple versionné et prévient (« using the EXAMPLE
configuration »). Un --outcome absent ou inconnu l'arrête avec la liste des clés. Il chiffre { ticket, headline, message, photos, lines, outcome } en AES-GCM (clé de 256 bits dérivée du mot de passe par PBKDF2, SHA-256, 120 000
itérations ; le mot de passe est comparé sans accents, casse, espaces ni ponctuation) et écrit
public/data/dossier.bin.
npm run check:spoilers (scripts/check-spoilers.ts) a besoin de dist/ (il
s'arrête sur « dist/ not found: run npm run build first. »). Il cherche dans chaque fichier .js, .html, .css,
.json et .txt de dist/ l'annonce, le texte du ticket (au-delà de deux mots) et les lignes de chaque issue, et la
première ligne du message ; il refuse un fichier privé dans dist/ (un dossier private, un fichier
*ending.config* ou *reveal.config*) et un dossier.bin qui contient ticket ou headline en clair. Sortie 1 avec
le nombre de fuites. Un jeu sans fin scellée n'a que la vérification des fichiers privés.
Limite ·
format-frozenLes champs du fichier scellé (ticket,headline,message,photos,lines,outcome) ne changent pas : undossier.bindéjà scellé reste valide.
check:spoilers affiche « ✔ No sealed-ending text in clear text in dist/. ». Jouez jusqu'à la fin (npm run dev) : le
ticket se gratte sur l'issue scellée, puis la carte montre son annonce, le message, les photos et les lignes, avec le
verdict sur le pronostic du joueur.
| Symptôme | Cause | Correction |
|---|---|---|
| Le jeu affiche « … » au lieu de la fin | le fichier manque à ending.file, ou le mot de passe diffère |
écrire file: 'data/dossier.bin' ; donner à la configuration le password du jeu |
⚠ … not found: using the EXAMPLE configuration |
pas de games/<GAME>/private/ending.config.ts
|
étape 1 |
Usage: npm run seal -- --outcome=<key> (keys: …) |
--outcome absent ou pas une clé de outcomes
|
passer une des clés listées |
✘ <fichier> contains in clear text: "…" |
un texte de fin est aussi dans le contenu du jeu | l'enlever du contenu : il n'a sa place que dans la configuration privée |
✘ private file in dist: … |
un fichier privé a été copié dans public/
|
l'enlever de public/
|
⚠ dist/data/dossier.bin missing (npm run seal not run?) |
aucun fichier scellé dans le build | étape 2, puis reconstruire |
-
games/<GAME>/private/ending.config.ts(le vôtre, jamais versionné :private/est dans.gitignore). -
public/data/dossier.bin, écrasé à chaqueseal.
Limite ·
one-dossier-per-repositorysealécritpublic/data/dossier.binà la racine du dépôt du moteur, quel que soit le jeu sélectionné : sceller un autre jeu remplace le fichier versionné de la démo. Rétablissez-le avecgit checkout public/data/dossier.binavant de committer, sauf si vous voulez le changer.
Sceller de nouveau avec un autre --outcome remplace le fichier ; le précédent n'est pas gardé.
git checkout public/data/dossier.bin ramène le fichier versionné.
-
src/engine/ending/seal.ts(le format et le chiffrement),src/engine/ending/index.ts(le côté lecteur). -
Mini-jeux intégrés (
scratch), Habillage et polices (les confettis et les sons), Commandes du jeu.
Generated publication · publication générée — current documentation · documentation courante: quest'n'click 4.4.0 r1, documentation revision · révision de la documentation 8dc717c69acb62c4742b69c54a7e7dfb620f75d8.
Earlier versions and permalinks · versions précédentes et liens permanents: https://wanoo.github.io/quest-n-click/docs/
An edit made in this wiki is overwritten at the next publication · une modification faite dans ce wiki est écrasée à la publication suivante.
Edit the source · Modifier la source · Report an error · Signaler une erreur
Index (6)
Démarrer (6)
Jouer (9)
Installer (17)
- Prérequis
- Installer depuis l'archive de la release
- Installer depuis npm, une fois publié
- Installer depuis le dépôt pour travailler sur le moteur
- doctor : vérifier sa machine
- Outils pour les images
- Outils audio : ffmpeg, fluidsynth, Furnace, uv
- Mettre à jour
- Notes de mise à jour : 4.4
- Notes de mise à jour : 4.3
- Notes de mise à jour : 4.2
- Notes de mise à jour : 4.1
- Notes de mise à jour : v3
- Notes de mise à jour : v2 vers v3
- Venir de web-scumm
- Référence du paquet
- Dépannage de l'installation
Créer un jeu (55)
- Votre premier jeu
- Organisation d'un projet créé et du dépôt du moteur
- La boucle de travail
- Principes du contenu et contrat d'identité
- Salles
- Géométrie : placement, zones de marche, masques, calques, caméra
- Un objet est visible mais inaccessible
- Réactions
- Commandes du jeu
- Conditions
- Drapeaux, variables et événements : lequel choisir
- Code sur mesure
- Personnages
- Objets et inventaire
- Carte du monde
- Dialogues
- Scripts et événements
- Faire bouger les personnages : patrouilles et marches
- Sorties
- Chapitres et objectifs
- État et sauvegardes : persistant ou temporaire, renommer un id, migrations
- Mise en scène : salles larges et animations
- La scène : lumières, particules, sols
- Habillage et polices
- Titre et générique
- Héros : plusieurs personnages et choix du héros
- Mini-jeux intégrés
- Un mini-jeu sur mesure
- Traductions
- Musique en stems
- Bruitages
- Voix : par langue et par héros
- Images : prompts, découpe des planches, transparence, échelle
- Provenance des assets
- Le storyboard, source de vérité
- Concevoir des énigmes
- Mécaniques classiques
- Pages de relecture
- Référence du DSL
- Vérifier son jeu
- Ce que prouve le solveur
- Options du solveur
- Playtests
- Remix
- Speedrun pour les auteurs
- La fin scellée
- Modèle de production
- Jeux d'exemple
- Travailler avec une IA
- Construire et publier un jeu
- Publier sur GitHub Pages
- Le jeu statique sur Clever Cloud
- Autres hébergeurs statiques
- Sous-chemin, cache et service worker, déploiement incomplet, retour arrière
- Tester sur un téléphone en réseau local
Studio local (24)
- Le Studio local : présentation et lancement
- Modifier une salle
- Placement et scène
- Aperçu, application, annulation
- Storyboard
- Assets et découpe
- Vérifier : validateur, solveur, chemin critique, chaleur, santé, couverture
- Captures avant et après
- Diff sémantique
- Jouer et rejouer une session
- Explication des règles
- Langue et objectifs
- Voix et matrice héros × langues
- Carte
- Notes
- Remix dans le Studio
- Musique
- L'Assistant : votre propre clé
- Mode démo et studio-apply
- Sécurité en local et en réseau local
- API du Studio
- MCP local : configurer chaque client
- Outils MCP
- Dépannage du Studio
Studio d'équipe (21)
- Ce qui tourne où
- Concepts : révision, transaction, pan, bail, aperçu, build
- Débuter comme dev invité
- Travailler ensemble au quotidien
- Rôles et actions : la matrice complète
- Invitations
- Gérer les membres
- Écriture refusée sur le Studio hébergé : révision de base périmée (409)
- Écriture refusée sur le Studio hébergé : pan verrouillé (423)
- Reprendre après un bail perdu, une déconnexion ou un aperçu périmé
- Commentaires
- Carte et diff sémantique
- Publier des builds
- MCP distant
- Le jeu dans Git
- Mettre à jour le moteur d'un jeu hébergé
- Assets hébergés
- La ligne de commande du serveur
- Routes de santé et de métriques
- L'essayer en local avec compose.yml
- Limites connues
Clever Cloud (23)
- Clever Cloud : vue d'ensemble, coût et prérequis
- Applications et add-ons
- Domaines et TLS
- Keycloak
- OIDC générique et GitLab
- Configuration
- Premier déploiement
- Sauvegardes
- RPO et RTO
- Exercice de restauration sur une installation vierge
- Redéploiements
- Mettre à jour le serveur et vérifier l'état après une migration
- Limites du retour arrière
- Supervision
- Sécurité
- Renouveler les clés
- Récupérer l'accès administrateur
- Changer de domaine ou de fournisseur OIDC
- Worker, PostgreSQL ou Cellar en panne
- Exporter le jeu et quitter l'installation
- Rétention
- Dépannage sur Clever Cloud
- Coûts et démontage
Reality Bridge et connecteurs (16)
- Le Reality Bridge : ce que c'est
- Démarrage rapide
- Garanties
- Installer et lancer le Bridge
- Sauvegarde et restauration
- Plusieurs tenants
- Signaux et manifeste
- La ligne de commande du Bridge
- Vue d'ensemble des connecteurs
- Connecteur email
- Connecteur Telnet
- Connecteur SSH
- Connecteur Open Badges
- Le SDK des connecteurs
- Sécurité : Biscuit et signatures
- Dépannage du Bridge et des connecteurs
Contribuer (25)
- Bienvenue
- Préparer son poste de développement
- La boucle de développement
- Avant une pull request
- Conventions
- Écrire la documentation
- Architecture
- Visite du code
- Frontières d'import
- Quels tests tournent quand
- Tests de mutation
- Le cliquet de couverture
- La référence de qualité
- La CI expliquée
- Passes de terrain
- Mesures de performance
- Publier une release
- Paquets npm
- Décisions et ADR
- Gouvernance
- Pull requests des bots
- Contribuer avec des agents IA
- Politique de sécurité
- Code de conduite
- Licences et crédits