qad3n/modport

Portez un mod Minecraft Java (n'importe quelle version, jar ou source) vers le chargeur de mods b1.7.3_rewrite en un seul fichier .b173mod fonctionnant côté client et serveur, en étendant le chargeur et le SDK là où le mod a besoin de quelque chose de nouveau. Utilisez-le lorsque l'utilisateur dit /modport, /port, "porte ce mod", ou remet un jar de mod à amener en bêta 1.7.3.

Qu'est-ce que modport ?

Ce skill permet de porter un mod Minecraft Java (n'importe quelle version) vers le chargeur de mods b1.7.3_rewrite, produisant un seul fichier .b173mod compatible client et serveur. Le processus implique une réécriture en Rust (guest wasm, SDK b173_api) en utilisant le mod décompilé comme spécification, pour obtenir le même aspect, la même sensation et le même gameplay dans b1.7.3. Il est destiné aux développeurs utilisant Claude Code ou un agent IA similaire, et fournit un ensemble d'outils bash (new_port.sh, inventory.sh, api.sh, test.sh, modtest.sh) pour automatiser la décompilation, l'inventaire des enregistrements, la conversion de modèles, l'extraction d'assets et les tests. Le skill gère deux modes : mode utilisateur par défaut (les extensions restent locales sans commit en amont) et mode mainteneur (l'utilisateur possède les dépôts). Il inclut des conseils détaillés sur le plan de travail, les exemples, l'extension du chargeur, et les pièges connus. Les mods sources proches de la bêta (1.7.10 plutôt que 1.12 ou 1.21) sont prioritaires car leurs modèles et données se correspondent presque 1:1.

Compatible avec✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/qad3n/b1.7.3-modport/tree/HEAD/skills/modport

Installed? Explore more Développement et programmation skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Porter un mod vers le chargeur b1.7.3_rewrite

Les mods Java ne peuvent pas s'exécuter. Un port est une réécriture en Rust (guest wasm, SDK b173_api) qui utilise le mod décompilé comme spécification. Objectif : même aspect, même sensation et même gameplay dans b1.7.3, à partir d'un seul fichier dans les dossiers mods/ côté client et serveur. Corrigez les bugs de source et optimisez librement tant que l'aspect et le gameplay restent les mêmes. Ne remplacez jamais un écran vanilla : une UI supplémentaire est une superposition activable/désactivable.

Ce fichier est la carte complète. Ne lisez pas la documentation de conception du chargeur ou de progression, les guides ou les fichiers SDK entiers pour vous orienter. Utilisez les outils, puis ouvrez uniquement le fichier d'exemple dont l'étape a besoin.

Espace de travail

Les chemins sont relatifs à la racine de l'espace de travail, le dossier qui contient b1.7.3_rewrite/, ports/ et le dépôt de la trousse à outils b1.7.3_modport/. Le install.sh de la trousse lie ses outils à tools/modport/ (écrit T/ ci-dessous) et ce skill à .claude/skills/modport ; depuis un dossier de port, T/ est ../../tools/modport/. Corrigez ou étendez les outils dans b1.7.3_modport/, jamais à l'intérieur d'un port. Sur une nouvelle machine, ou lorsqu'un outil échoue à cause d'une dépendance manquante, exécutez T/doctor.sh : cela affiche la commande qui comble chaque lacune. Tous les outils sont en bash : sous Windows, ils s'exécutent dans Git Bash (l'outil Bash de Claude Code sur Windows) et gèrent eux-mêmes les .exe, py et les chemins. Appelez les outils Python via T/py.sh, jamais python3 directement.

Modes

Vérifiez une fois par session : test -f .modport-maintainer dans la racine de l'espace de travail.

  • Mode mainteneur (le marqueur existe) : les dépôts du chargeur, du SDK et de la trousse appartiennent à cet utilisateur. Ne les engagez (commit) et ne les poussez (push) que lorsque l'utilisateur le demande, comme indiqué dans les étapes ci-dessous.
  • Mode utilisateur (pas de marqueur, par défaut) : les dépôts du chargeur, du SDK et de la trousse appartiennent à leur auteur en amont.
    • Les extensions du chargeur et du SDK restent dans l'arbre de travail local. Ne les engagez jamais dans ces dépôts, ne les poussez jamais vers leurs dépôts distants, n'exécutez jamais gh pr create, gh issue create ou toute autre commande gh en écriture contre eux, même si on vous demande de « partager » ou de « remonter » un changement. Dites à l'utilisateur de le faire lui-même.
    • Consignez chaque modification du chargeur ou du SDK dans ports/<modid>/LOADER_CHANGES.md : ce qu'elle ajoute, pourquoi, quels fichiers.
    • Dites à l'utilisateur qu'un port nécessitant une modification locale du chargeur ne fonctionne que sur son chargeur patché, pas sur un chargeur standard.
    • Le dossier du port est le propre dépôt de l'utilisateur : engagez-y quando demandé, poussez uniquement vers un dépôt distant que l'utilisateur a configuré.
    • Ne créez jamais le fichier marqueur.

Outils

OutilUtilisez-le quandSortie
T/new_port.sh <modid> <jar> [nom]Au démarrage d'un port. Écrit les manifests, git init, décompile dans reference/src (Vineflower, téléchargé et vérifié lors de la première utilisation), exécute l'inventaireports/<modid>/
T/inventory.sh <src>Pour lister ce qu'un mod enregistre : blocs, objets et entités avec classes, tuiles, modèles, moteurs de rendu, GUI, génération du monde, événements~15 Ko pour un grand mod, conservé dans reference/inventory.txt
T/api.shAvant d'écrire du code contre le SDK. sdk <fichier> (world, register, screen, behavior, events, terrain, config, services), spec <struct>, enum <nom> (HostCall, EntityField, ModelOp), templates, events, console, hooksune ligne par signature avec les numéros de ligne du SDK
T/py.sh extract_assets.py <jar> <modid>Une fois, depuis le dossier du port. Textures, sons et lang dans assets/<modid>, clés de langue mappées à tile.<modid>.x.name, item.<modid>.x.name, <modid>.<key>jamais engagé
T/py.sh convert_models.py --out src/models/generated.rs <Model.java>... [--arg Model.scale=0.5]Modèles. Constructeurs de ModelBase (noms SRG ou MCP) en pièces et boîtes. Enveloppez l'appel dans le tools/convert_models.sh du portRust généré, jamais modifié à la main
T/test.sh deploy ports/<modid> [--game]Chaque cycle de test. Construit, arrête le serveur de test, installe le mod seul, démarre le serveur. --game reconstruit d'abord le jeu et cargo-b173 (après des modifications du chargeur ou du SDK). Refuse pendant qu'un serveur de test tourne : une autre session peut le posséder, demandez avant --forcefin de la console du serveur
T/test.sh errors [n]Première chose après tout écheclignes de panique, piège et erreur des deux journaux
T/modtest.sh cmd <ligne_console> / log server 80Conduire et vérifier le serveuruniquement les lignes de réponse
T/modtest.sh client / shot <png>Vérifications visuelles uniquement. Demandez à l'utilisateur avant de lancer un client : cela ouvre une fenêtre sur son bureauPNG de la fenêtre du jeu

Console (T/modtest.sh cmd loader ..., syntaxe de T/api.sh console) : gen, map (PNG vue de dessus), slice (coupe verticale PNG), column (vérifiez avant tp : un joueur téléporté dans le terrain suffoque), fill, tp, use, interact, close, entities, summon, slot, tile. Lisez les PNG avec l'outil Read. Mettez les chaînes de vérification répétées dans de petits scripts dans ports/<modid>/tools/ au lieu de les retaper.

Flux de travail

  1. Configuration. Choisissez la version source la plus proche de la bêta (1.7.10 plutôt que 1.12 plutôt que 1.21) : ses modèles, textures et formes de données se correspondent presque 1:1. Les jars 1.7.10 utilisent des noms SRG (func_, field_) : lisez le sens à partir de l'utilisation, ne chassez pas les correspondances. Exécutez new_port.sh, puis extract_assets.py. Copiez les classes de modèles vanilla qu'un modèle de mod étend dans reference/vanilla/ pour le convertisseur. Les extras d'actifs spécifiques au port (sprites des moteurs de rendu 3D) vont dans le propre script tools/ du port.
  2. Planification. Transformez reference/inventory.txt en lignes TODO dans PORT_STATUS.md dans l'ordre des dépendances : blocs et objets, recettes, génération du monde et dimension, entités, machines et GUI, structures, boss, systèmes de joueur, emplacements supplémentaires, comportements des objets, sons et particules, configuration. Les jalons se terminent par un déploiement et une vérification en console.
  3. Portage module par module. Lisez la classe du mod, vérifiez le SDK avec api.sh, copiez le modèle d'un exemple. Citez la classe source dans PORT_STATUS.md, pas dans les commentaires du code.
  4. Étendez le chargeur uniquement lorsque api.sh ne montre aucune manière (liste de contrôle ci-dessous).
  5. Testez après chaque module avec deploy, cmd, errors. Tenez une liste de bugs dans PORT_STATUS.md au lieu de boucler sur un seul problème ; corrigez la liste à la fin.
  6. Terminez. Mettez à jour PORT_STATUS.md. Exécutez cargo +nightly fmt dans le port et cargo clippy dans b1.7.3_rewrite. Engagez uniquement sur demande : un port contient du code source Rust, des outils et des manifests, jamais d'actifs, reference/ ou des fichiers d'IA. ports/ est soit un dépôt git par port, soit un monorepo avec un dossier par mod ; new_port.sh détecte lequel. En mode utilisateur, listez les modifications locales du chargeur dont le port a besoin à partir de LOADER_CHANGES.md dans le rapport final.

Exemples

Exemples du SDK, toujours présents : b1.7.3_rewrite/vendor/b1.7.3-modding-sdk/examples/ avec testmod (chaque module d'API dans un fichier), ruby (contenu uniquement de données), energy, energy_api, machines (services entre mods).

Un port terminé, quand l'espace de travail en a un, est la carte la plus rapide. Le port Aether (ports/aether/src) :

BesoinFichier
Tableau des blocs, modèles, comportementsblocks.rs (un tableau de constantes par rangée par type)
Objets, outils, armures, nourriture, recettesitems.rs, tools.rs, gear.rs, recipes.rs
Options de configurationconfig.rs (portez chaque jet de taux d'apparition, ceux manquants inondent le monde)
Enregistrement des entités et aidesentities/mod.rs
Mob passif et monture, hostile, volant, projectileentities/phyg.rs + mount.rs, cockatrice.rs, zephyr.rs, projectile.rs
État d'entité visible par le cliententities/swet.rs, entities/moa.rs (setSynced/synced)
Modèles et animationmodels/mod.rs (part, cuboid, Program ; copiez-le dans un nouveau port)
Boss, barre de vie du boss, écran de dialogueentities/bosses/mod.rs, valkyrie_queen.rs (écran transparent() plus canal côté serveur)
Machine avec GUI et données de tuilemachines.rs (ScreenBuilder, #[tile_behavior])
Emplacements d'équipement supplémentaires, couches de renduaccessories.rs (screens().overlay("GuiInventory", ..), playerLayer)
Mouvement local du joueurplayer.rs (côté client dans TickPost, état serveur dans des cartes thread_local par identifiant d'entité)
Dimension, terrain, décorationworld/mod.rs, world/terrain.rs, world/decorate.rs
Structuresworld/dungeons/mod.rs, writer.rs (terrain::structure::candidates, clip à StructureBox::populated, compressez les hauteurs 256 en 128)
Portail et voyageportal.rs

Formes qui s'appliquent toujours : les appels GL du moteur de rendu deviennent des opérations Program (push, translate, rotate, scale, texture, blend, éclairage) dans le pose de l'entité ; onLivingUpdate/updateEntityActionState vont dans onAi (remplace l'IA modèle) ou onTick ; terrain::Random et les ports de bruit gardent les graines identiques ; vérifiez isAuthority() avant de changer le monde (le joueur unique renvoie les paquets en boucle, même code des deux côtés) ; validez chaque charge utile côté serveur ; chat via translate("<modid>.gui.…") ; sons comme <modid>.<chemin.avec.points> ; textures comme <modid>:<chemin>.

Formes de données (API du chargeur 1.1, ABI 3). L'identité est toujours par nom, jamais par identifiant numérique :

  • Variantes de blocs et orientation. La metadata source ou les états de bloc deviennent des états nommés : ctx.blocks().states(nom, BlockStatesSpec) ou data/<modid>/states/<bloc>.toml.

    • Listez les valeurs de chaque propriété dans l'ordre de la metadata source, afin que le code ctx.meta() continue de fonctionner.
    • Un bloc avec plus de 16 états reçoit des identifiants cachés supplémentaires du chargeur. Lisez et écrivez un tel bloc uniquement via world.blockState/setBlockState ou ctx.state()/setState().
    • Les textures par état vont dans variants.
  • Données par pile. Le NBT des objets et les capacités deviennent des composants de données : stackComponent/setStackComponent avec un StackRef.

    • Un mod écrit uniquement les composants <modid>:*.
    • Les piles avec des composants différents ne fusionnent jamais.
    • Les dégâts restent la durabilité. Utilisez un objet par variante au lieu de sous-types de dégâts.
  • Données sur des choses que le mod ne possède pas. Le NBT ou les capacités des entités, joueurs, tuiles, chunks et monde deviennent des emplacements par mod :

    • entité : entity.setData ou setSynced
    • joueur : player.setData(clé, ..)
    • tuile : world.setTileAttachment
    • chunk : world.setChunkAttachment
    • monde : setWorldData

    Chaque emplacement est indexé par l'identifiant du mod, donc deux mods n'entrent jamais en conflit.

  • Modifications du contenu vanilla ou d'autres mods. Les modifications de propriétés (dureté, luminosité, inflammabilité, outil) deviennent ctx.blocks().modify(BlockModifySpec) ou data/<modid>/modify/blocks/*.toml. Les modifications des listes d'apparition deviennent modifySpawns ou modify/spawns/*.toml. La vitesse de minage pour une classe d'outil provient des tags minecraft:mineable/<pioche|hache|pelle>. Les modifications conflictuelles sont signalées dans l'écran du chargeur de mods. Ne remplacez jamais un bloc vanilla entier pour un changement de propriété.

  • Génération du monde et commandes.

    • Nommez chaque fonctionnalité de génération du monde de manière unique. Le nom détermine son aléatoire, donc les autres mods ne le décalent jamais.
    • Les commandes répondent à /<modid>:<nom>. Le raccourci /<nom> va au premier mod qui l'enregistre.

Étendre le chargeur

Fonctionnalités générales uniquement, jamais un hack pour un seul mod. Les chemins ci-dessous sont dans b1.7.3_rewrite/. Points de contact, dans l'ordre :

  1. Protocole : ajoutez des variantes à la fin de HostCall, GuestCall, GuestReply ou EntityField dans vendor/b1.7.3-modding-sdk/mod_protocol/src/abi.rs ; les nouveaux champs de spec dans spec.rs comme types Option ou Default (les structs de spec sont #[serde(default)], donc les anciens mods se chargent toujours). Les contrats publiés ne changent jamais : un contrat modifié reçoit une nouvelle version.
  2. Hôte : bras de correspondance dans crates/modloader/src/host/world.rs (appels runtime) ou host/register.rs (phase d'enregistrement) ; les systèmes plus importants dans leur propre crates/modloader/src/<system>.rs ou extensions.rs. Les nouveaux modèles sont des lignes dans crates/modloader/src/entities.rs (ENTITY_TEMPLATES) ou content/templates.rs (BLOCK_TEMPLATES).
  3. Wrapper SDK à côté de ses frères dans b173_api/src/{world,register,screen}.rs, dans le prélude si les mods l'utilisent partout.
  4. Côté client dans crates/client/src/modded/. Le code vanilla appelle un nouveau comportement via un crochet d'une ligne avec un commentaire // rewrite:, listé avec une version dans crates/modloader/hooks.toml.
  5. Outils de console de développement dans crates/modloader/src/devtools.rs (ajoutez à USAGE).
  6. cargo build et cargo clippy, puis T/test.sh deploy ports/<modid> --game. Notez l'ajout là où l'espace de travail tient les notes du chargeur. Mode mainteneur : les modifications du SDK sont engagées dans le sous-module SDK, puis mises à jour dans la réécriture, uniquement sur demande de l'utilisateur. Mode utilisateur : rien n'y est engagé, le changement va dans LOADER_CHANGES.md.

Chaîne d'exemple, World::lightning : HostCall::Lightning (abi.rs) vers son bras dans host/world.rs vers le wrapper dans b173_api/src/world.rs.

Pièges connus

  • HostCall, HostReply et les structs de spec sont encodés en postcard. N'ajoutez jamais de champ à une struct existante : les invités ABI 2 cesseraient de décoder. Les nouvelles données nécessitent une nouvelle variante ou une nouvelle struct.

  • T/modtest.sh pilote un serveur et client de test partagé (b1.7.3_rewrite/target/modtest, serveur dans son server/). Ne jamais arrêter, réinitialiser ou prendre le contrôle d'une autre session sans demander à l'utilisateur.

  • cargo b173 build exécute déjà la compilation wasm ; il n'y a pas d'étape cargo build séparée.

  • Modification du chargeur ou du SDK sans deploy --game : le serveur exécute toujours l'ancien binaire sans les nouveaux appels hôte.

  • La fenêtre du client de test perd le focus et ouvre le menu pause ; c'est le harnais, pas le port.

Skills associés