Caputchin
Développement de jeu pour le marketplace

Le manifeste caputchin.json

caputchin.json à la racine de ton dépôt est la source de vérité pour l'auteur et l'indexeur d'un jeu du marketplace. L'indexeur le lit côté serveur pour apprendre l'identité du jeu, où vit son bundle, quels préréglages il offre, et comment le rejouer. Il n'est jamais lu dans le navigateur ; le SDK ne le charge pas à l'exécution.

Cette page est la référence des champs. Pour la construction, vois Bâtir un jeu pour le marketplace ; pour la publication, vois Publier au marketplace. Les types exacts sont exportés du SDK sous GameManifest (vois la référence du SDK).

Un jeu unique minimal

{
  "terms_accepted": true,
  "license": "MIT",
  "marketplace": {
    "name": "Leaf Memory",
    "description": "Match pairs of tropical leaves before the timer runs out.",
    "preview": "preview.png"
  },
  "npm": "@your-org/leaf-memory",
  "entry": "dist/leaf-memory.js"
}

Champs de premier niveau

ChampRequisBut
terms_acceptedpour l'indexationDoit être le littéral true pour confirmer que tu acceptes les Conditions de soumission au Marketplace. Toute autre valeur (ou manquante) retire le manifeste de l'index. Les manifestes auto-hébergés-seulement peuvent l'omettre.
licensepour l'indexationUn identifiant ou une expression SPDX couvrant ton code et tes ressources embarquées. Doit s'évaluer en un identifiant approuvé (vois la référence des erreurs de publication).
marketplacepour l'indexationLa présence est le signal « indexe-moi ». Absent signifie un jeu auto-hébergé valide que le marketplace ignore. Vois Le bloc marketplace.
npmavec entryCoordonnée de paquet npm que l'indexeur résout en une URL jsDelivr.
entryavec npmChemin relatif au dépôt vers le bundle construit. entry, npm, ou les deux doivent être présents pour un jeu exécutable.
gamespour les collectionsChemins de sous-manifestes pour un wrapper de collection. Mutuellement exclusif avec entry / npm. Vois Collections.
runoptionnelUn artefact de rejeu headless dédié. Vois L'artefact run.
preferredoptionnelIndices de présentation que l'hôte PEUT honorer. Vois Le bloc preferred.
locales / skins / configurationsoptionnelBlocs de préréglages consommés par le SDK dans l'iframe. Vois Blocs de préréglages.

Il n'y a pas de champ version : l'indexeur épingle lui-même le bundle à une ref immuable (la version npm publiée ou le SHA de commit résolu).

Le bloc marketplace

ChampBut
nameTitre de la carte. Retombe sur le nom du dépôt (unique / wrapper) ou le nom du dossier feuille (enfant de collection).
descriptionSous-titre de la carte et corps de la page de détail.
previewChemin d'image (relatif à la racine du dépôt) ou URL absolue. Environ 600x315, sujet centré.
versionChaîne de version affichage-seul pour la page de détail. Optionnel.
supportIndicateurs de compatibilité déclarés par l'auteur (responsive, touch, accessible, audio, ...), jamais vérifiés par la plateforme ; remontés comme filtres et icônes de carte.
author{ name?, url?, email? } optionnel. name / url se rendent comme une signature d'auteur sur la page de détail ; email n'est jamais montré et est l'opt-in pour les e-mails d'échec de publication. Les trois sous-champs sont indépendants.

Le bloc est entièrement optionnel. Omets name / url et la page de détail ne montre simplement aucune signature d'auteur (le propriétaire GitHub montré ailleurs sur la page est une identité distincte, toujours présente, pas un repli pour cette signature). Omets email et tu ne reçois aucune notification d'échec de publication. Ne règle que les sous-champs que tu veux.

Pointeurs de distribution

L'indexeur épingle le bundle de chaque jeu à une ref immuable pour que le hash d'intégrité stocké reste valide, et re-résout à chaque passage (cron quotidien plus « Publier ou mettre à jour » manuel) :

  • entry + npm se résolvent en cdn.jsdelivr.net/npm/<npm>@<resolved-version>/<entry>.
  • entry seul se résout en cdn.jsdelivr.net/gh/<owner>/<repo>@<commit-sha>/<entry>.
  • npm seul se résout en l'entrée par défaut du paquet à la version épinglée.

Il n'y a pas d'épinglage de version côté utilisateur ; pour geler un build, un utilisateur l'auto-héberge via le game-src du widget (jeu personnalisé).

L'artefact run

Par défaut, l'auto-vérification de rejeu exécute ton bundle entry en direct. Quand ton jeu est grand ou basé sur un framework ou du WASM, livre plutôt un artefact run headless dédié et léger :

{
  "run": {
    "entry": "dist/run.js",
    "modules": [
      { "name": "sim.wasm", "type": "wasm", "path": "dist/sim.wasm" }
    ]
  }
}
ChampSignification
run.entryChemin relatif au dépôt vers le bundle run headless (l'export run du contrat de rejeu).
run.modulesTableau optionnel d'entrées de modules que le run importe par name.

Contraintes que l'indexeur applique

Celles-ci sont validées au moment de l'indexation ; une violation fait échouer la publication avec une manifest-error (vois la référence des erreurs de publication).

run.entry :

  • Doit être du JavaScript : le nom de base doit correspondre à [a-zA-Z0-9_-]+.js. L'artefact run est toujours du JS (le WASM est livré comme module, ci-dessous).
  • Doit être un chemin propre relatif au dépôt : pas de barre oblique en tête, pas de traversée .., pas d'espace, pas de ? / #, pas de préfixe scheme://.

Chaque entrée run.modules[] est { name, type, path } :

  • name doit correspondre à [a-zA-Z0-9_-]+.(wasm|js) : un module est soit du JS soit du WASM, rien d'autre. Le name est le spécificateur d'import que l'entrée utilise.
  • type doit s'accorder avec l'extension : wasm pour un nom .wasm, js pour un nom .js.
  • name ne doit pas être un nom réservé (entry.js, artifact.js) que l'hôte de rejeu utilise en interne.
  • name doit être unique dans le tableau (pas de doublons).
  • path doit être un chemin propre relatif au dépôt (mêmes règles que run.entry).
  • Au plus 16 modules.

Omets run pour rejouer l'entry en direct directement. Vois le contrat de rejeu pour ce que l'artefact doit exporter.

Le bloc preferred

Le bloc preferred optionnel porte des indices de présentation. Chaque clé est consultative : l'hôte PEUT l'honorer, et elle ne remplace jamais un attribut d'embed explicite.

{
  "preferred": { "width": 360, "height": 480, "layout": "modal" }
}

Un jeu responsive qui devrait remplir son conteneur par défaut peut déclarer "full" sur l'un ou l'autre axe :

{
  "preferred": { "width": "full", "height": 480 }
}
ChampSignification
width / heightUne empreinte en pixels, ou le littéral "full". Le widget l'applique quand l'embed laisse width / height non réglé (une valeur d'embed explicite, y compris full, l'emporte). Une valeur en pixels dimensionne l'iframe à ce nombre ; "full" étire cet axe pour remplir le parent, le même effet qu'un width="full" d'embed. Omets pour retomber sur l'empreinte par défaut intégrée du widget.
layoutLe shell que le widget bâtit autour du jeu : inline, modal ou fullscreen. Utilisé seulement quand l'embed laisse layout non réglé (son défaut auto). Ordre de résolution : l'attribut layout de l'embed, puis ce layout préféré, puis inline.

Ces indices ne sont honorés que pour les jeux que la plateforme résout côté serveur (jeux du marketplace, ou un id de jeu donné sans clé de site). Un bundle game-src auto-hébergé que la plateforme ne peut pas lire avant le montage ignore à la fois l'empreinte et l'indice de layout.

Blocs de préréglages

locales, skins et configurations déclarent chacun un schema optionnel (types par clé et documentation) plus presets (les banques d'options nommées). Le widget résout le choix du visiteur contre ceux-ci et remet à ton jeu le résultat aplati comme ctx. Le catalogue complet des types de champs est la référence du schéma de personnalisation partagée ; les mêmes types pilotent le schéma de tableau de bord d'un jeu personnalisé.

Un champ skins.schema peut être un color, une ressource (image / audio / video), ou un scalaire (boolean, number, range, list) en utilisant les mêmes formes de contrainte que configurations ({ "type": "range", "min": 0, "max": 24 }, ["dots","stripes"], etc.). Les valeurs de skin scalaires se résolvent en leur valeur typée dans ctx.skin (un number est un vrai nombre), exactement comme une valeur de configuration ; les valeurs de couleur et de ressource se résolvent en chaînes.

Le _theme d'un préréglage de skin déclare le mode dans lequel il fonctionne : light, dark, ou any (l'omettre signifie any). Un préréglage light ou dark ne s'affiche que dans ce mode ; un préréglage any se lit sur les deux fonds et est éligible pour les deux. Il y a un défaut par mode. Un préréglage marqué _default: true est le défaut pour le ou les modes pour lesquels il est éligible, donc un défaut any couvre les deux ; quand plusieurs préréglages éligibles sont marqués défaut pour un mode, le premier dans l'ordre de déclaration le gagne. Liste un préréglage spécifique au mode au-dessus d'un any pour donner à ce mode un skin dédié pendant que le préréglage any retombe sur l'autre.

Les fichiers de découpe .caputchin/

Les blocs de préréglages (surtout les jeux de locales complets) rendent caputchin.json long. Déplace n'importe quel axe dans son propre fichier sous un dossier .caputchin/, laissant le manifeste court :

caputchin.json
.caputchin/locales.json
.caputchin/skins.json
.caputchin/configurations.json

L'objet de premier niveau de chaque fichier est ce bloc d'axe ({ schema?, presets }). Les trois sont optionnels. La préséance est un remplacement d'axe entier, caputchin.json l'emporte : si un axe est déclaré à la fois en ligne et comme fichier, le bloc en ligne est utilisé et le fichier est ignoré (la publication avertit pour que tu saches qu'il était mort). Garde chaque axe à un seul endroit.

Collections

Un dépôt peut livrer plusieurs jeux. Un wrapper de collection déclare des chemins d'enfants au lieu de entry / npm :

{
  "marketplace": { "name": "Caputchin Core Pack", "description": "The official pack." },
  "games": ["./packages/leaf-memory", "./packages/dino-runner"]
}

Chaque chemin pointe vers un répertoire enfant tenant son propre caputchin.json. Les ids d'enfants sont owner/repo/<leaf-dir>. Omets le bloc marketplace du wrapper pour indexer les enfants sans page de collection.

Voir aussi

Sur cette page