Appearance
ModBlock
1. La Mécanique d'Enregistrement Couplé (Block & Blockitem)
Dans Minecraft Forge 1.20.1, un bloc physique présent dans le monde et l'objet (l'item) que le joueur tient dans sa main pour le poser sont deux objets distincts dans le code. Pour créer un bloc fonctionnel standard, il faut obligatoirement enregistrer le Block ET son BlockItem associé.
Structure d'enregistrement standard avec Deferred Register :
java
public static final DeferredRegister<Block> BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MonMod.MODID);
public static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, MonMod.MODID);
// 1. Enregistrement du Bloc
public static final RegistryObject<Block> MON_BLOC = BLOCKS.register("mon_bloc",
() -> new Block(BlockBehaviour.Properties.of().mapColor(MapColor.STONE).strength(2.0F, 6.0F).sound(SoundType.STONE))
);
// 2. Enregistrement de l'Item de Bloc correspondant
public static final RegistryObject<Item> MON_BLOC_ITEM = ITEMS.register("mon_bloc",
() -> new BlockItem(MON_BLOC.get(), new Item.Properties())
);⚠️ Règle d'or : L'identifiant de registre (ici
"mon_bloc") DOIT être rigoureusement identique pour leBlocket leBlockItemafin que le jeu lie correctement les textures et les correspondances d'inventaire.
On préférera séparer le block et le blockItem en mettant le block dans ModBlock et le blockItem dans ModItem
2. Les Propriétés de Configuration via BlockBehaviour.Properties
Tout comme les items possèdent leur classe interne de configuration, les blocs s'appuient sur BlockBehaviour.Properties (souvent instancié via la méthode de fabrique courte BlockBehaviour.Properties.of() ou en copiant un bloc existant avec copy(Blocks.STONE)).
Liste des méthodes incontournables :
| Méthode du Builder | Effet et Description Technique |
|---|---|
strength(float hardness, float resistance) | Définit le temps requis pour casser le bloc (dureté) et sa résistance face aux explosions de TNT (Ex : Pierre = 1.5F, 6.0F). |
.strength(float equalValue) | Assigne une valeur identique à la dureté et à la résistance aux explosions. |
.instabreak() | Le bloc se brise instantanément à la main ou à l'outil (Dureté = 0.0F), comme pour les fleurs ou les torches. |
sound(SoundType type) | Assigne les sons émis par le bloc (quand on marche dessus, le pose, le brise, ou le frappe) (ex : SoundType.STONE, WOOD, GRASS). |
lightLevel(Function<BlockState, Integer>) | Définit la luminosité émise par le bloc de 0 à 15, via une fonction dynamique basée sur son état (Ex : (state) -> 15). |
.friction(float value) | Modifie la glisse du bloc. Par défaut 0.6F (Glace = 0.98F). Cela influe sur l'accélération des entités marchant dessus. |
.speedFactor(float value) | Multiplicateur de vitesse de déplacement des entités (ex : 0.4F pour ralentir fortement comme le Sable des Âmes). |
.jumpFactor(float value) | Multiplicateur de puissance de saut des entités (ex : pour créer un bloc trampoline). |
.noCollision() | Le bloc perd sa boîte de collision solide. Les entités peuvent passer au travers (comportement des herbes, des lianes et des fluides). |
.noOcclusion() | Indique au moteur de rendu que le bloc est transparent ou n'occupe pas un cube plein. Empêche le jeu de masquer les faces des blocs adjacents (évite les bugs visuels de "X-Ray"). |
.requiresCorrectToolForDrops() | Si cette méthode est chaînée, le bloc ne donnera aucun loot s'il est brisé avec un mauvais outil (ex : casser de la pierre sans pioche). |
.randomTicks() | Inscrit le bloc sur la liste des mises à jour aléatoires du monde. Indispensable pour que la méthode randomTick() de votre classe soit appelée (ex : croissance des plantes, propagation du feu). |
3. L'Architecture des Classes de Blocs Spécialisés
Pour créer des blocs possédant des fonctionnalités complexes et des comportements de jeu natifs (mécaniques redstone, orientations, ouvertures), on n'utilise pas la classe générique Block. On fait hériter notre bloc de classes spécialisées de Minecraft.
Hiérarchie des classes de blocs courantes :
BlockLiquidBlock(Pour les fluides comme l'eau ou la lave)HorizontalDirectionalBlock(Blocs orientables sur l'axe horizontal, ex: Fours)BedBlock(Le lit)BaseEntityBlock(Blocs liés à une TileEntity / BlockEntity, ex: Coffres)DoorBlock(Gestion des portes sur 2 blocs de haut)TrapDoorBlock(Gestion des trappes et de leur bascule)SlabBlock(Les demi-dalles, gère la position basse, haute ou double)StairBlock(Les escaliers, requiert unBlockStatede référence dans son constructeur)
Signatures des constructeurs complexes et pièges fréquents :
StairBlock(Escaliers) : Requiert leBlockStated'un bloc parent pour copier ses propriétés et textures de particules en plus des propriétés physiques.
java
new StairBlock(() -> Blocks.STONE.defaultBlockState(), BlockBehaviour.Properties.copy(Blocks.STONE))SlabBlock(Dalles) &DoorBlock/TrapDoorBlock: Ces classes se contentent de récupérer les propriétés classiques, mais modifient profondément la gestion interne des états graphiques du bloc (lesBlockStateProperties).
java
new DoorBlock(BlockBehaviour.Properties.of().strength(3.0F), BlockSetType.OAK)(Note : En 1.20.1, un BlockSetType est requis pour les bruits d'ouverture).
4. Systèmes Avancés: BlockStates et Récolte (Loot Tables & Outils)
La gestion des États (BlockStates)
Un seul et unique bloc en jeu peut avoir plusieurs apparences ou états logiques (ex: un levier activé/désactivé, une porte ouverte/fermée). Cela est défini par les Property. Pour implémenter cela dans une classe personnalisée, on surcharge deux méthodes :
java
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(BlockStateProperties.HORIZONTAL_FACING, BlockStateProperties.POWERED);
}
@Override
public BlockState getStateForPlacement(BlockPlaceContext context) {
return this.defaultBlockState()
.setValue(BlockStateProperties.HORIZONTAL_FACING, context.getHorizontalDirection().getOpposite())
.setValue(BlockStateProperties.POWERED, false);
}Déclaration de la Récolte (Tags et Niveaux de Minage via Datagen)
En 1.20.1, le fait qu'un outil puisse casser ou non un bloc proprement ne se gère plus directement dans le code Java du bloc, mais via le système de Tags JSON (générés par Data Generation ou manuellement dans le dossier src/main/resources/data/minecraft/tags/blocks/).
Type d'outil requis : Associer le bloc au fichier
mineable/pickaxe,mineable/axe,mineable/shovel, oumineable/hoe.Niveau du matériau requis (Tier) : Associer le bloc aux tags de paliers de vanilla :
needs_stone_tool: Pioche en pierre minimum (pour le Fer).needs_iron_tool: Pioche en fer minimum (pour le Diamant).needs_diamond_tool: Pioche en diamant minimum (pour l'Obsidienne).Spécificité Forge :
needs_netherite_toolou l'utilisation des tags de niveaux numériques Forge pour les tiers personnalisés.
💡 Synthèse pour les examens / fiches pratiques : Si on configure un minerai personnalisé avec
requiresCorrectToolForDrops()en Java, mais qu'on oublie d'ajouter le bloc dans le tag JSONmineable/pickaxeetneeds_iron_tool, le bloc se cassera très lentement avec n'importe quel outil et ne donnera jamais sa ressource. Le couplage Code + JSON (ou Datagen) est impératif en 1.20.1.