Faites un clic droit pour créer un buisson qui peut être récolté
--Une classe pour l'enregistrement des blocs et des éléments ajoutés et une classe proxy sont préparées.
Remarques: Je n'ai rien écrit sur le nouveau processus, je l'ai juste assigné à une variable vanilla.
--1.12.2 - ItemFood.class - ItemSeed.class - BlockCrops.class - BlockCarrots.class - apple.json - acacia_sapling.json - carrots.json --1.14.4 - SweetBerryBushBlock.class
Je voudrais ajouter un arbre anzu (récolte anzu de ce mod) Remarques: veuillez préparer une classe d'inscription
Le nom du paquet est un homme vanille
src/main/java --FFFMItems.java (classe pour l'enregistrement des éléments) - oguro.fffm.init --FFFMBlocks.java (classe d'enregistrement de bloc) - oguro.fffm.init --BlockFruitTree.java (classe qui détermine les caractéristiques des arbres fruitiers) - oguro.fffm.block --BlockApricotTree.java (Classe qui détermine les propriétés uniques d'Anzu Tree) - oguro.fffm.block --ItemFruit.java (classe qui détermine les caractéristiques des fruits) - oguro.fffm.item --ItemApricot.java (Classe qui détermine les propriétés uniques d'Anzu) - oguro.fffm.item --ItemSapling.java (Classe qui détermine les propriétés des plants d'arbres fruitiers) - oguro.fffm.item --ItemApricotSapling.java (Classe qui détermine les propriétés uniques des semis Anzu) - oguro.fffm.item
Remarques: Je n'ai pas préparé le json qui ressemble à l'inventaire Block Apricot Tree car il ne sera pas affiché dans l'inventaire à moins que j'utilise une commande, mais c'est ennuyeux car une erreur apparaît dans le journal, il est donc préférable de le préparer (ça a l'air bien). C'est bon parce que ça ne peut pas être lu
--apricot.json (Apparition d'Anzu) - assets.fffm.models.item --apricot_tree_sapling.json (Apparence des semis d'Anzu) - assets.fffm.models.item --apricot_tree (Puisque les blocs de l'arbre Anzu sont plusieurs blocs avec des métadonnées différentes, le json qui décrit l'apparence de chacun est un fichier qui spécifie lequel) - assets.fffm.blockstates
--apricot.png (texture de anzu) - assets.fffm.textures.items --apricot_tree_sapling.png (texture des semis d'anzu) - assets.fffm.textures.items
FFFMItems.java
package oguro.fffm.init;
import java.util.LinkedList;
import java.util.List;
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraft.item.Item;
import net.minecraft.item.ItemFood;
import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import oguro.fffm.FFFMRef;
import oguro.fffm.item.ItemApricot;
import oguro.fffm.item.ItemApricotTreeSapling;
import oguro.fffm.item.ItemSapling;
public class FFFMItems
{
//アイテムを宣言する
public static ItemSapling APRICOT_TREE_SAPLING;
public static ItemFood APRICOT;
//アイテムのインスタンスを生成する
public static void init()
{
APRICOT_TREE_SAPLING = (ItemSapling) new ItemApricotTreeSapling(FFFMBlocks.APRICOT_TREE).setRegistryName("apricot_tree_sapling")
.setUnlocalizedName("apricot_tree_sapling");
APRICOT = (ItemFood) new ItemApricot().setRegistryName("apricot")
.setUnlocalizedName("apricot");
}
//アイテムを登録する
public static void register()
{
registerItem(APRICOT_TREE_SAPLING);
registerItem(APRICOT);
}
public static void registerItem(Item item)
{
RegistrationHandler.ITEMS.add(item);
}
//アイテムの描画を登録する
public static void registerRenders()
{
registerRender(APRICOT_TREE_SAPLING);
registerRender(APRICOT);
}
private static void registerRender(Item item)
{
ModelLoader.setCustomModelResourceLocation(item, 0,
new ModelResourceLocation(item.getRegistryName(),"inventory"));
}
//内部クラスでアイテムを登録する
@Mod.EventBusSubscriber(modid = FFFMRef.MODID)
public static class RegistrationHandler
{
public static final List<Item> ITEMS = new LinkedList<>();
@SubscribeEvent
public static void registerItems(final RegistryEvent.Register<Item> event)
{
FFFMItems.init();
FFFMItems.register();
ITEMS.stream().forEach(item -> event.getRegistry().register(item));
}
}
}
FFFMBlocks.java
package oguro.fffm.init;
import java.util.LinkedList;
import java.util.List;
import net.minecraft.block.Block;
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock;
import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import oguro.fffm.FFFMRef;
import oguro.fffm.block.BlockApricotTree;
import oguro.fffm.block.BlockFruitTree;
public class FFFMBlocks
{
//登録するブロックを宣言
public static BlockFruitTree APRICOT_TREE;
//ブロックのインスタンスを生成
public static void init()
{
APRICOT_TREE = (BlockFruitTree) new BlockApricotTree().setRegistryName("apricot_tree")
.setUnlocalizedName("apricot_tree");
}
//ブロックを登録する
public static void register()
{
registerBlock(APRICOT_TREE);
}
//ブロックの登録
public static void registerBlock(Block block)
{
registerBlock(block, new ItemBlock(block));
}
//アイテムブロックの登録
public static void registerBlock(Block block, ItemBlock item)
{
RegistrationHandler.BLOCKS.add(block);
item.setRegistryName(block.getRegistryName());
FFFMItems.RegistrationHandler.ITEMS.add(item);
}
//アイテムブロックの描画を登録する
public static void registerRenders()
{
registerRender(APRICOT_TREE);
}
@SideOnly(Side.CLIENT)
private static void registerRender(Block block)
{
ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(block), 0,
new ModelResourceLocation(block.getRegistryName(),"inventory"));
}
//内部クラスでブロックを登録する
@Mod.EventBusSubscriber(modid = FFFMRef.MODID)
public static class RegistrationHandler {
public static final List<Block> BLOCKS = new LinkedList<>();
@SubscribeEvent
public static void registerItems(final RegistryEvent.Register<Block> event) {
FFFMBlocks.init();
FFFMBlocks.register();
BLOCKS.stream().forEach(block -> event.getRegistry().register(block));
}
}
}
BlockFruitTree.java
package oguro.fffm.block;
import java.util.Random;
import net.minecraft.block.Block;
import net.minecraft.block.BlockBush;
import net.minecraft.block.IGrowable;
import net.minecraft.block.SoundType;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.properties.PropertyInteger;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.init.SoundEvents;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import oguro.fffm.init.FFFMItems;
// En remodelant BlockCrops, j'ai travaillé sur l'obtention de fruits du bloc SweetBerry Bush de la 1.14.4.
//新しいフルーツを追加するときは、このクラスを継承してドロップするアイテムなどの変数を書き換えることにする。
public class BlockFruitTree
extends BlockBush
implements IGrowable
{
//作物の成長段階を作る。ここでは0から3の4段階。
public static final PropertyInteger AGE = PropertyInteger.create("age", 0, 3);
protected BlockFruitTree()
{
this.setDefaultState(this.blockState.getBaseState().withProperty(this.getAgeProperty(), Integer.valueOf(0)));
this.setTickRandomly(true);
this.setCreativeTab((CreativeTabs)null);
this.setHardness(0.0F);
this.setSoundType(SoundType.PLANT);
this.disableStats();
}
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
{
return FULL_BLOCK_AABB;
}
//成長に関する記述
protected boolean canSustainBush(IBlockState state)
{
//設置可能(作付け可能)なブロック
//BlockFruitTreeでは「耕地(FARMLAND)」、「草ブロック(GRASS)」、「土(DIRT)」の上に植えられるようにした。
return state.getBlock() == Blocks.FARMLAND ||
state.getBlock() == Blocks.GRASS ||
state.getBlock() == Blocks.DIRT;
}
protected PropertyInteger getAgeProperty()
{
return AGE;
}
public int getMaxAge()
{
//最大成長段階は今回は3
return 3;
}
protected int getAge(IBlockState state)
{
return ((Integer)state.getValue(this.getAgeProperty())).intValue();
}
public IBlockState withAge(int age)
{
return this.getDefaultState().withProperty(this.getAgeProperty(), Integer.valueOf(age));
}
public boolean isMaxAge(IBlockState state)
{
return ((Integer)state.getValue(this.getAgeProperty())).intValue() >= this.getMaxAge();
}
public void updateTick(World worldIn, BlockPos pos, IBlockState state, Random rand)
{
super.updateTick(worldIn, pos, state, rand);
if (!worldIn.isAreaLoaded(pos, 1)) return; // Forge: prevent loading unloaded chunks when checking neighbor's light
if (worldIn.getLightFromNeighbors(pos.up()) >= 9)
{
int i = this.getAge(state);
if (i < this.getMaxAge())
{
float f = getGrowthChance(this, worldIn, pos);
if(net.minecraftforge.common.ForgeHooks.onCropsGrowPre(worldIn, pos, state, rand.nextInt((int)(25.0F / f) + 1) == 0))
{
worldIn.setBlockState(pos, this.withAge(i + 1), 2);
net.minecraftforge.common.ForgeHooks.onCropsGrowPost(worldIn, pos, state, worldIn.getBlockState(pos));
}
}
}
}
public void grow(World worldIn, BlockPos pos, IBlockState state)
{
int i = this.getAge(state) + this.getBonemealAgeIncrease(worldIn);
int j = this.getMaxAge();
if (i > j)
{
i = j;
}
worldIn.setBlockState(pos, this.withAge(i), 2);
}
protected int getBonemealAgeIncrease(World worldIn)
{
return MathHelper.getInt(worldIn.rand, 2, 5);
}
protected static float getGrowthChance(Block blockIn, World worldIn, BlockPos pos)
{
float f = 4.0F;
BlockPos blockpos = pos.down();
for (int i = -1; i <= 1; ++i)
{
for (int j = -1; j <= 1; ++j)
{
float f1 = 0.0F;
IBlockState iblockstate = worldIn.getBlockState(blockpos.add(i, 0, j));
if (iblockstate.getBlock().canSustainPlant(iblockstate, worldIn, blockpos.add(i, 0, j), net.minecraft.util.EnumFacing.UP, (net.minecraftforge.common.IPlantable)blockIn))
{
f1 = 4.0F;
if (iblockstate.getBlock().isFertile(worldIn, blockpos.add(i, 0, j)))
{
f1 = 5.2F;
}
}
if (i != 0 || j != 0)
{
f1 /= 6.0F;
}
f += f1;
}
}
BlockPos blockpos1 = pos.north();
BlockPos blockpos2 = pos.south();
BlockPos blockpos3 = pos.west();
BlockPos blockpos4 = pos.east();
boolean flag = blockIn == worldIn.getBlockState(blockpos3).getBlock() || blockIn == worldIn.getBlockState(blockpos4).getBlock();
boolean flag1 = blockIn == worldIn.getBlockState(blockpos1).getBlock() || blockIn == worldIn.getBlockState(blockpos2).getBlock();
if (flag && flag1)
{
f /= 2.0F;
}
else
{
boolean flag2 = blockIn == worldIn.getBlockState(blockpos3.north()).getBlock() || blockIn == worldIn.getBlockState(blockpos4.north()).getBlock() || blockIn == worldIn.getBlockState(blockpos4.south()).getBlock() || blockIn == worldIn.getBlockState(blockpos3.south()).getBlock();
if (flag2)
{
f /= 4.8F;
}
}
return f;
}
//破壊したときに落とす「苗アイテム」の設定
//このクラスはどの果樹からも直接呼び出されない予定なのでとりあえずあんずの苗にしておく。
protected Item getSapling()
{
return FFFMItems.APRICOT_TREE_SAPLING;
}
//破壊したときに落とす「果物」とその個数の設定
//このクラスはどの果樹からも直接呼び出されない予定なのでとりあえずあんずを2個にしておく。
protected Item getFruit()
{
return Items.APRICOT;
}
protected int getHowManyPickUp()
{
return 2;
}
//ドロップするようにする
public Item getItemDropped(IBlockState state, Random rand, int fortune)
{
return this.getSapling();
}
public ItemStack getItem(World worldIn, BlockPos pos, IBlockState state)
{
return new ItemStack(this.getSapling());
}
public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
{
int i = this.getAge(state);
boolean flag = i == 3;
if (!flag && playerIn.getHeldItem(hand).getItem() == Items.DYE) {
return false;
}
//age=2(準最大成長)のときに収穫する処理
else if (i == 2)
{
//収穫できる個数
//getHowManyPickUpで設定した収穫個数だけ収穫できる設定にしてある。
int j = getHowManyPickUp();
spawnAsEntity(worldIn, pos, new ItemStack(getFruit(), j + (flag ? 1 : 0)));
//収穫時に鳴らす音
//新しい音を追加せずに「額縁からアイテムを剥ぎ取る音」にした。
worldIn.playSound((EntityPlayer)null, pos, SoundEvents.ENTITY_ITEMFRAME_REMOVE_ITEM, SoundCategory.BLOCKS, 1.0F, 0.8F + worldIn.rand.nextFloat() * 0.4F);
worldIn.setBlockState(pos, this.withAge(Integer.valueOf(0)), 2);
return true;
}
//age=3(最大成長)のときに収穫する処理
else if (i == 3)
{
//収穫できる個数
//getHowManyPickUpで設定した収穫個数の2倍を収穫できる設定にしてある。
int j = getHowManyPickUp() * 2;
spawnAsEntity(worldIn, pos, new ItemStack(getFruit(), j + (flag ? 1 : 0)));
//収穫時に鳴らす音
//新しい音を追加せずに「額縁からアイテムを剥ぎ取る音」にした。
worldIn.playSound((EntityPlayer)null, pos, SoundEvents.ENTITY_ITEMFRAME_REMOVE_ITEM, SoundCategory.BLOCKS, 1.0F, 0.8F + worldIn.rand.nextFloat() * 0.4F);
worldIn.setBlockState(pos, this.withAge(Integer.valueOf(0)), 2);
return true;
}
//age=2に満たないときは「収穫しない処理
else
{
return super.onBlockActivated(worldIn, pos, state, playerIn, hand, facing, hitX, hitY, hitZ);
}
}
//IGrowableに関する記述
@Override
public boolean canGrow(World worldIn, BlockPos pos, IBlockState state, boolean isClient)
{
return !this.isMaxAge(state);
}
@Override
public boolean canUseBonemeal(World worldIn, Random rand, BlockPos pos, IBlockState state)
{
return true;
}
@Override
public void grow(World worldIn, Random rand, BlockPos pos, IBlockState state)
{
this.grow(worldIn, pos, state);
}
//成長段階ごとのブロックをメタデータの異なるブロックとして管理
public IBlockState getStateFromMeta(int meta)
{
return this.withAge(meta);
}
public int getMetaFromState(IBlockState state)
{
return this.getAge(state);
}
protected BlockStateContainer createBlockState()
{
return new BlockStateContainer(this, new IProperty[] {AGE});
}
}
BlockApricotTree.java
package oguro.fffm.block;
import net.minecraft.item.Item;
import oguro.fffm.init.FFFMItems;
public class BlockApricotTree
extends BlockFruitTree
{
//苗アイテムを設定
protected Item getSapling()
{
return FFFMItems.APRICOT_TREE_SAPLING;
}
//果物アイテムを設定
protected Item getFruit()
{
return FFFMItems.APRICOT;
}
//収穫できる個数を設定
protected int getHowManyPickUp()
{
return 2;
}
}
ItemFruit.java
package oguro.fffm.item;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.EnumAction;
import net.minecraft.item.ItemFood;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResult;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumHand;
import net.minecraft.world.World;
import oguro.fffm.creativetab.FFFMCreativeTabs;
public class ItemFruit
extends ItemFood
{
//満腹度回復量
protected static int getHealAmount()
{
return 5;
}
//オオカミが食べるかどうか
protected static boolean canWolfEat()
{
return false;
}
//食べるのにかかる時間
protected int getEatTime()
{
return 32;
}
//食べるときのアニメーション
//デフォルトでEAT
public EnumAction getItemUseAction(ItemStack stack)
{
return EnumAction.EAT;
}
//満腹でも食べられるか
//デフォルトでいいえ
protected boolean canEatAlways()
{
return false;
}
public ItemFruit()
{
super(getHealAmount(), canWolfEat());
this.setCreativeTab(FFFMCreativeTabs.FFFM_FRUIT);
}
public int getMaxItemUseDuration(ItemStack stack)
{
return getEatTime();
}
public ActionResult<ItemStack> onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn)
{
ItemStack itemstack = playerIn.getHeldItem(handIn);
if (playerIn.canEat(canEatAlways()))
{
playerIn.setActiveHand(handIn);
return new ActionResult<ItemStack>(EnumActionResult.SUCCESS, itemstack);
}
else
{
return new ActionResult<ItemStack>(EnumActionResult.FAIL, itemstack);
}
}
}
ItemApricot.java
package oguro.fffm.item;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.EnumAction;
import net.minecraft.item.ItemFood;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResult;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumHand;
import net.minecraft.world.World;
import oguro.fffm.creativetab.FFFMCreativeTabs;
public class ItemFruit
extends ItemFood
{
//満腹度回復量
protected static int getHealAmount()
{
return 5;
}
//オオカミが食べるかどうか
protected static boolean canWolfEat()
{
return false;
}
//食べるのにかかる時間
protected int getEatTime()
{
return 32;
}
//食べるときのアニメーション
//デフォルトでEAT
public EnumAction getItemUseAction(ItemStack stack)
{
return EnumAction.EAT;
}
//満腹でも食べられるか
//デフォルトでいいえ
protected boolean canEatAlways()
{
return false;
}
public ItemFruit()
{
super(getHealAmount(), canWolfEat());
this.setCreativeTab(FFFMCreativeTabs.FFFM_FRUIT);
}
public int getMaxItemUseDuration(ItemStack stack)
{
return getEatTime();
}
public ActionResult<ItemStack> onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn)
{
ItemStack itemstack = playerIn.getHeldItem(handIn);
if (playerIn.canEat(canEatAlways()))
{
playerIn.setActiveHand(handIn);
return new ActionResult<ItemStack>(EnumActionResult.SUCCESS, itemstack);
}
else
{
return new ActionResult<ItemStack>(EnumActionResult.FAIL, itemstack);
}
}
}
ItemSapling.java
package oguro.fffm.item;
import net.minecraft.advancements.CriteriaTriggers;
import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.common.IPlantable;
import oguro.fffm.block.BlockFruitTree;
import oguro.fffm.creativetab.FFFMCreativeTabs;
import oguro.fffm.init.FFFMBlocks;
//バニラのItemSeedを引っ張ってきたっぽい(覚えてない)。
//新しいフルーツを追加するときは、このクラスを継承して植える果樹などの変数を書き換えることにする。
public class ItemSapling
extends Item
implements IPlantable
{
private final BlockFruitTree crops;
protected Block getTree()
{
//植える果樹
//このクラスはどの果樹からも直接呼び出されない予定なのでとりあえずあんずの木にしておく。
return FFFMBlocks.APRICOT_TREE;
}
public ItemSapling(BlockFruitTree fruit_tree)
{
this.crops = (BlockFruitTree) this.getTree();
//クリエイティブタブ
//私は新しく「FFFM_SAPLING」というクリエイティブタブを作ってそこに入れた。
// Si vous souhaitez utiliser l'onglet créatif de Vanilla tel quel, this.setCreativeTab (CreativeTabs.FOOD);
this.setCreativeTab(FFFMCreativeTabs.FFFM_SAPLINGS);
}
public EnumActionResult onItemUse(EntityPlayer player, World worldIn, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
{
ItemStack itemstack = player.getHeldItem(hand);
net.minecraft.block.state.IBlockState state = worldIn.getBlockState(pos);
if (facing == EnumFacing.UP && player.canPlayerEdit(pos.offset(facing), facing, itemstack) && state.getBlock().canSustainPlant(state, worldIn, pos, EnumFacing.UP, (IPlantable) this) && worldIn.isAirBlock(pos.up()))
{
worldIn.setBlockState(pos.up(), this.crops.getDefaultState());
if (player instanceof EntityPlayerMP)
{
CriteriaTriggers.PLACED_BLOCK.trigger((EntityPlayerMP)player, pos.up(), itemstack);
}
itemstack.shrink(1);
return EnumActionResult.SUCCESS;
}
else
{
return EnumActionResult.FAIL;
}
}
@Override
public net.minecraftforge.common.EnumPlantType getPlantType(net.minecraft.world.IBlockAccess world, BlockPos pos)
{
return net.minecraftforge.common.EnumPlantType.Plains;
}
@Override
public net.minecraft.block.state.IBlockState getPlant(net.minecraft.world.IBlockAccess world, BlockPos pos)
{
return this.crops.getDefaultState();
}
}
ItemApricotTreeSapling.java
package oguro.fffm.item;
import net.minecraft.block.Block;
import oguro.fffm.block.BlockFruitTree;
import oguro.fffm.init.FFFMBlocks;
public class ItemApricotTreeSapling extends ItemSapling {
public ItemApricotTreeSapling(BlockFruitTree fruit_tree) {
super(fruit_tree);
}
//植える果樹
@Override
protected Block getTree()
{
return FFFMBlocks.APRICOT_TREE;
}
}
Il peut être possible de faire 2 cases de hauteur en jouant avec json et le jugement de frappe de classe
apricot.json
{
"parent": "item/generated",
"textures": {
"layer0": "fffm:items/apricot"
}
}
apricot_tree_sapling.json
{
"parent": "item/generated",
"textures": {
"layer0": "fffm:blocks/apricot_tree_sapling"
}
}
apricot_tree.json
{
"variants": {
"age=0": { "model": "fffm:apricot_tree_stage0" },
"age=1": { "model": "fffm:apricot_tree_stage1" },
"age=2": { "model": "fffm:apricot_tree_stage2" },
"age=3": { "model": "fffm:apricot_tree_stage3" }
}
}
apricot_tree_stage◯.json Jouez avec les nombres en ◯
{
"parent": "block/cross",
"textures": {
"cross": "fffm:blocks/apricot_tree_stage◯"
}
}